summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-02-15 02:15:32 +0000
commit86464aed71025541805e7b1515541aee89879e33 (patch)
treee01a457a4912a8553bc65524aa3125d51f29f810 /drivers
parent88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff)
Merge with Linux 2.2.1.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acorn/block/fd1772.c6
-rw-r--r--drivers/acorn/block/ide-ics.c8
-rw-r--r--drivers/acorn/char/Config.in11
-rw-r--r--drivers/acorn/char/Makefile13
-rw-r--r--drivers/acorn/char/keyb_ps2.c355
-rw-r--r--drivers/acorn/char/mouse_rpc.c86
-rw-r--r--drivers/acorn/net/ether1.c10
-rw-r--r--drivers/acorn/net/etherh.c10
-rw-r--r--drivers/acorn/scsi/acornscsi.c144
-rw-r--r--drivers/acorn/scsi/cumana_2.c2
-rw-r--r--drivers/acorn/scsi/eesox.c2
-rw-r--r--drivers/acorn/scsi/fas216.c2
-rw-r--r--drivers/acorn/scsi/powertec.c2
-rw-r--r--drivers/ap1000/ddv_util.c2
-rw-r--r--drivers/block/Config.in2
-rw-r--r--drivers/block/acsi.c4
-rw-r--r--drivers/block/acsi_slm.c13
-rw-r--r--drivers/block/ataflop.c2
-rw-r--r--drivers/block/cmd640.c6
-rw-r--r--drivers/block/floppy.c1
-rw-r--r--drivers/block/genhd.c121
-rw-r--r--drivers/block/hd.c1
-rw-r--r--drivers/block/ide-cd.c111
-rw-r--r--drivers/block/ide-cd.h68
-rw-r--r--drivers/block/ide-disk.c118
-rw-r--r--drivers/block/ide-dma.c30
-rw-r--r--drivers/block/ide-floppy.c3
-rw-r--r--drivers/block/ide-pci.c23
-rw-r--r--drivers/block/ide-probe.c15
-rw-r--r--drivers/block/ide-tape.c82
-rw-r--r--drivers/block/ide.c68
-rw-r--r--drivers/block/ide.h2
-rw-r--r--drivers/block/ll_rw_blk.c81
-rw-r--r--drivers/block/loop.c1
-rw-r--r--drivers/block/nbd.c14
-rw-r--r--drivers/block/opti621.c85
-rw-r--r--drivers/block/paride/Config.in1
-rw-r--r--drivers/block/paride/Makefile9
-rw-r--r--drivers/block/paride/friq.c282
-rw-r--r--drivers/block/paride/frpw.c11
-rw-r--r--drivers/block/paride/jumbo8
-rw-r--r--drivers/block/paride/on26.c23
-rw-r--r--drivers/block/paride/paride.c8
-rw-r--r--drivers/block/paride/pg.c8
-rw-r--r--drivers/block/paride/pseudo.h22
-rw-r--r--drivers/block/paride/pt.c2
-rw-r--r--drivers/block/pdc4030.c8
-rw-r--r--drivers/block/ps2esdi.c1
-rw-r--r--drivers/block/raid1.c3
-rw-r--r--drivers/block/rz1000.c4
-rw-r--r--drivers/block/xd.c2
-rw-r--r--drivers/block/z2ram.c96
-rw-r--r--drivers/cdrom/cdrom.c86
-rw-r--r--drivers/cdrom/cdu31a.c23
-rw-r--r--drivers/cdrom/mcdx.c2
-rw-r--r--drivers/cdrom/mcdx.h1
-rw-r--r--drivers/cdrom/sbpcd.c28
-rw-r--r--drivers/cdrom/sjcd.c6
-rw-r--r--drivers/cdrom/sonycd535.c23
-rw-r--r--drivers/char/Config.in40
-rw-r--r--drivers/char/Makefile16
-rw-r--r--drivers/char/README.epca8
-rw-r--r--drivers/char/bttv.c1295
-rw-r--r--drivers/char/bttv.h52
-rw-r--r--drivers/char/busmouse.c4
-rw-r--r--drivers/char/c-qcam.c202
-rw-r--r--drivers/char/c-qcam.h18
-rw-r--r--drivers/char/console.c29
-rw-r--r--drivers/char/consolemap.c13
-rw-r--r--drivers/char/cyclades.c89
-rw-r--r--drivers/char/epca.c9
-rw-r--r--drivers/char/ftape/RELEASE-NOTES4
-rw-r--r--drivers/char/ftape/lowlevel/fdc-io.c15
-rw-r--r--drivers/char/hfmodem/Config.in2
-rw-r--r--drivers/char/hfmodem/main.c2
-rw-r--r--drivers/char/i2c.c11
-rw-r--r--drivers/char/isicom.c1951
-rw-r--r--drivers/char/istallion.c2
-rw-r--r--drivers/char/joystick/Config.in6
-rw-r--r--drivers/char/keyboard.c9
-rw-r--r--drivers/char/lp_m68k.c21
-rw-r--r--drivers/char/mac_SCC.c35
-rw-r--r--drivers/char/macmouse.c312
-rw-r--r--drivers/char/mem.c56
-rw-r--r--drivers/char/misc.c10
-rw-r--r--drivers/char/msbusmouse.c4
-rw-r--r--drivers/char/msp3400.c414
-rw-r--r--drivers/char/msp3400.h22
-rw-r--r--drivers/char/n_tty.c22
-rw-r--r--drivers/char/pc_keyb.c124
-rw-r--r--drivers/char/pcxx.c1
-rw-r--r--drivers/char/pms.c2
-rw-r--r--drivers/char/radio-aimslab.c1
-rw-r--r--drivers/char/radio-gemtek.c310
-rw-r--r--drivers/char/radio-zoltrix.c169
-rw-r--r--drivers/char/random.c12
-rw-r--r--drivers/char/riscom8.c6
-rw-r--r--drivers/char/rtc.c2
-rw-r--r--drivers/char/saa5249.c2
-rw-r--r--drivers/char/serial.c63
-rw-r--r--drivers/char/specialix.c8
-rw-r--r--drivers/char/stallion.c2
-rw-r--r--drivers/char/tpqic02.c4
-rw-r--r--drivers/char/tty_io.c42
-rw-r--r--drivers/char/tty_ioctl.c4
-rw-r--r--drivers/char/tuner.c48
-rw-r--r--drivers/char/videodev.c70
-rw-r--r--drivers/char/vt.c1
-rw-r--r--drivers/fc4/fc.c2
-rw-r--r--drivers/fc4/fcp_scsi.h2
-rw-r--r--drivers/fc4/soc.c4
-rw-r--r--drivers/isdn/Config.in2
-rw-r--r--drivers/isdn/avmb1/b1lli.c6
-rw-r--r--drivers/isdn/hisax/callc.c9
-rw-r--r--drivers/isdn/hisax/config.c2
-rw-r--r--drivers/isdn/icn/icn.h4
-rw-r--r--drivers/isdn/isdn_common.c208
-rw-r--r--drivers/isdn/isdn_common.h6
-rw-r--r--drivers/isdn/isdn_net.c42
-rw-r--r--drivers/isdn/isdn_ppp.c25
-rw-r--r--drivers/isdn/isdn_x25iface.c2
-rw-r--r--drivers/macintosh/macserial.c2
-rw-r--r--drivers/macintosh/mediabay.c8
-rw-r--r--drivers/macintosh/via-pmu.c16
-rw-r--r--drivers/misc/Makefile5
-rw-r--r--drivers/misc/parport_arc.c3
-rw-r--r--drivers/misc/parport_ax.c5
-rw-r--r--drivers/misc/parport_ieee1284.c23
-rw-r--r--drivers/misc/parport_init.c8
-rw-r--r--drivers/misc/parport_pc.c4
-rw-r--r--drivers/misc/parport_procfs.c29
-rw-r--r--drivers/net/3c501.c70
-rw-r--r--drivers/net/3c503.c1
-rw-r--r--drivers/net/3c505.c88
-rw-r--r--drivers/net/3c509.c52
-rw-r--r--drivers/net/3c515.c15
-rw-r--r--drivers/net/3c523.c35
-rw-r--r--drivers/net/3c59x.c1020
-rw-r--r--drivers/net/82596.c2
-rw-r--r--drivers/net/8390.c195
-rw-r--r--drivers/net/8390.h64
-rw-r--r--drivers/net/Config.in13
-rw-r--r--drivers/net/Makefile44
-rw-r--r--drivers/net/Space.c21
-rw-r--r--drivers/net/ac3200.c1
-rw-r--r--drivers/net/acenic.c408
-rw-r--r--drivers/net/acenic.h21
-rw-r--r--drivers/net/acenic_firmware.h7957
-rw-r--r--drivers/net/apne.c30
-rw-r--r--drivers/net/ariadne2.c5
-rw-r--r--drivers/net/at1700.c218
-rw-r--r--drivers/net/bmac.c101
-rw-r--r--drivers/net/cops.h2
-rw-r--r--drivers/net/cosa.c1909
-rw-r--r--drivers/net/cosa.h102
-rw-r--r--drivers/net/daynaport.c4
-rw-r--r--drivers/net/de4x5.c178
-rw-r--r--drivers/net/de4x5.h1
-rw-r--r--drivers/net/dgrs.c4
-rw-r--r--drivers/net/dgrs_i82596.h4
-rw-r--r--drivers/net/e2100.c1
-rw-r--r--drivers/net/eepro.c972
-rw-r--r--drivers/net/eepro100.c2
-rw-r--r--drivers/net/eexpress.c5
-rw-r--r--drivers/net/epic100.c1285
-rw-r--r--drivers/net/es3210.c1
-rw-r--r--drivers/net/eth16i.c4
-rw-r--r--drivers/net/fmv18x.c96
-rw-r--r--drivers/net/hamradio/Config.in4
-rw-r--r--drivers/net/hamradio/baycom_ser_fdx.c1
-rw-r--r--drivers/net/hamradio/baycom_ser_hdx.c1
-rw-r--r--drivers/net/hamradio/hdlcdrv.c3
-rw-r--r--drivers/net/hamradio/scc.c255
-rw-r--r--drivers/net/hamradio/soundmodem/sm.c1
-rw-r--r--drivers/net/hp-plus.c1
-rw-r--r--drivers/net/hp.c1
-rw-r--r--drivers/net/hp100.c28
-rw-r--r--drivers/net/ibmtr.c20
-rw-r--r--drivers/net/irda/.cvsignore2
-rw-r--r--drivers/net/irda/Config.in17
-rw-r--r--drivers/net/irda/Makefile80
-rw-r--r--drivers/net/irda/actisys.c314
-rw-r--r--drivers/net/irda/esi.c194
-rw-r--r--drivers/net/irda/irport.c403
-rw-r--r--drivers/net/irda/irtty.c748
-rw-r--r--drivers/net/irda/pc87108.c1502
-rw-r--r--drivers/net/irda/tekram.c314
-rw-r--r--drivers/net/irda/uircc.c914
-rw-r--r--drivers/net/irda/w83977af_ir.c1273
-rw-r--r--drivers/net/lance.c284
-rw-r--r--drivers/net/lne390.c1
-rw-r--r--drivers/net/ltpc.c20
-rw-r--r--drivers/net/ne.c841
-rw-r--r--drivers/net/ne2.c13
-rw-r--r--drivers/net/ne2k-pci.c1
-rw-r--r--drivers/net/ne3210.c1
-rw-r--r--drivers/net/net_init.c82
-rw-r--r--drivers/net/pcnet32.c130
-rw-r--r--drivers/net/plip.c60
-rw-r--r--drivers/net/ppp.c23
-rw-r--r--drivers/net/rcif.h299
-rw-r--r--drivers/net/rclanmtl.c2307
-rw-r--r--drivers/net/rclanmtl.h637
-rw-r--r--drivers/net/rcpci45.c1419
-rw-r--r--drivers/net/rrunner.c247
-rw-r--r--drivers/net/rrunner.h3
-rw-r--r--drivers/net/sdla.c6
-rw-r--r--drivers/net/sdla_fr.c6
-rw-r--r--drivers/net/sdla_ppp.c2
-rw-r--r--drivers/net/sdla_x25.c5
-rw-r--r--drivers/net/sdladrv.c2
-rw-r--r--drivers/net/sdlamain.c12
-rw-r--r--drivers/net/seeq8005.c8
-rw-r--r--drivers/net/sktr.c16
-rw-r--r--drivers/net/sktr_firmware.h2
-rw-r--r--drivers/net/slhc.c59
-rw-r--r--drivers/net/smc-mca.c1
-rw-r--r--drivers/net/smc-ultra.c1
-rw-r--r--drivers/net/smc-ultra32.c1
-rw-r--r--drivers/net/tlan.c2
-rw-r--r--drivers/net/tulip.c2090
-rw-r--r--drivers/net/via-rhine.c13
-rw-r--r--drivers/net/wd.c1
-rw-r--r--drivers/net/yellowfin.c17
-rw-r--r--drivers/net/z85230.c8
-rw-r--r--drivers/net/znet.c4
-rw-r--r--drivers/nubus/nubus.c2
-rw-r--r--drivers/pci/oldproc.c33
-rw-r--r--drivers/pci/pci.c8
-rw-r--r--drivers/pci/pcisyms.c8
-rw-r--r--drivers/pci/quirks.c28
-rw-r--r--drivers/pnp/parport_probe.c8
-rw-r--r--drivers/sbus/audio/amd7930.c2
-rw-r--r--drivers/sbus/audio/dbri.h2
-rw-r--r--drivers/sbus/char/bpp.c4
-rw-r--r--drivers/sbus/char/sab82532.c2
-rw-r--r--drivers/sbus/char/su.c2
-rw-r--r--drivers/sbus/char/vfc_i2c.c4
-rw-r--r--drivers/scsi/AM53C974.c4
-rw-r--r--drivers/scsi/ChangeLog.ncr53c8xx13
-rw-r--r--drivers/scsi/Config.in31
-rw-r--r--drivers/scsi/Makefile52
-rw-r--r--drivers/scsi/NCR5380.c2
-rw-r--r--drivers/scsi/NCR53C9x.c256
-rw-r--r--drivers/scsi/NCR53C9x.h69
-rw-r--r--drivers/scsi/NCR53c406a.c8
-rw-r--r--drivers/scsi/README.aic7xxx65
-rw-r--r--drivers/scsi/README.ncr53c8xx4
-rw-r--r--drivers/scsi/README.tmscsim73
-rw-r--r--drivers/scsi/advansys.c11
-rw-r--r--drivers/scsi/aha152x.c9
-rw-r--r--drivers/scsi/aic7xxx.c793
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.reg4
-rw-r--r--drivers/scsi/aic7xxx_proc.c149
-rw-r--r--drivers/scsi/atari_dma_emul.c2
-rw-r--r--drivers/scsi/atp870u.c2037
-rw-r--r--drivers/scsi/atp870u.h72
-rw-r--r--drivers/scsi/dc390.h4
-rw-r--r--drivers/scsi/eata_dma.c4
-rw-r--r--drivers/scsi/eata_dma_proc.c1
-rw-r--r--drivers/scsi/eata_pio.c2
-rw-r--r--drivers/scsi/eata_pio_proc.c1
-rw-r--r--drivers/scsi/fd_mcs.c4
-rw-r--r--drivers/scsi/fdomain.c277
-rw-r--r--drivers/scsi/g_NCR5380.c8
-rw-r--r--drivers/scsi/gdth.c2883
-rw-r--r--drivers/scsi/gdth.h493
-rw-r--r--drivers/scsi/gdth_ioctl.h13
-rw-r--r--drivers/scsi/gdth_proc.c337
-rw-r--r--drivers/scsi/gdth_proc.h6
-rw-r--r--drivers/scsi/hosts.c65
-rw-r--r--drivers/scsi/hosts.h10
-rw-r--r--drivers/scsi/i91uscsi.c2808
-rw-r--r--drivers/scsi/i91uscsi.h857
-rw-r--r--drivers/scsi/ibmmca.c4
-rw-r--r--drivers/scsi/ide-scsi.c5
-rw-r--r--drivers/scsi/imm.c491
-rw-r--r--drivers/scsi/imm.h98
-rw-r--r--drivers/scsi/ini9100u.c1147
-rw-r--r--drivers/scsi/ini9100u.h335
-rw-r--r--drivers/scsi/mac_NCR5380.c8
-rw-r--r--drivers/scsi/mac_esp.c691
-rw-r--r--drivers/scsi/mac_esp.h41
-rw-r--r--drivers/scsi/mac_scsi.c2
-rw-r--r--drivers/scsi/mca_53c9x.c476
-rw-r--r--drivers/scsi/mca_53c9x.h66
-rw-r--r--drivers/scsi/megaraid.c1353
-rw-r--r--drivers/scsi/megaraid.h284
-rw-r--r--drivers/scsi/mesh.c10
-rw-r--r--drivers/scsi/ncr53c8xx.c36
-rw-r--r--drivers/scsi/ncr53c8xx.h19
-rw-r--r--drivers/scsi/ppa.c295
-rw-r--r--drivers/scsi/ppa.h58
-rw-r--r--drivers/scsi/scsi.c30
-rw-r--r--drivers/scsi/scsi.h4
-rw-r--r--drivers/scsi/scsi_debug.c6
-rw-r--r--drivers/scsi/scsi_error.c14
-rw-r--r--drivers/scsi/scsi_obsolete.c44
-rw-r--r--drivers/scsi/scsi_proc.c7
-rw-r--r--drivers/scsi/scsi_syms.c2
-rw-r--r--drivers/scsi/scsiiom.c570
-rw-r--r--drivers/scsi/sd.c18
-rw-r--r--drivers/scsi/seagate.c8
-rw-r--r--drivers/scsi/sr.c12
-rw-r--r--drivers/scsi/st.c9
-rw-r--r--drivers/scsi/tmscsim.c577
-rw-r--r--drivers/scsi/tmscsim.h14
-rw-r--r--drivers/scsi/wd7000.c10
-rw-r--r--drivers/sound/Config.in39
-rw-r--r--drivers/sound/Makefile13
-rw-r--r--drivers/sound/README.FIRST1
-rw-r--r--drivers/sound/README.blurb10
-rw-r--r--drivers/sound/README.wavefront375
-rw-r--r--drivers/sound/Readme186
-rw-r--r--drivers/sound/Readme.cards1227
-rw-r--r--drivers/sound/Readme.linux85
-rw-r--r--drivers/sound/Readme.modules99
-rw-r--r--drivers/sound/ad1816.c1417
-rw-r--r--drivers/sound/ad1848.c184
-rw-r--r--drivers/sound/audio.c7
-rw-r--r--drivers/sound/cs4232.c48
-rw-r--r--drivers/sound/dev_table.c6
-rw-r--r--drivers/sound/dev_table.h19
-rw-r--r--drivers/sound/dmabuf.c27
-rw-r--r--drivers/sound/dmasound.c132
-rw-r--r--drivers/sound/es1370.c50
-rw-r--r--drivers/sound/es1371.c87
-rw-r--r--drivers/sound/gus_card.c9
-rw-r--r--drivers/sound/gus_wave.c11
-rw-r--r--drivers/sound/legacy.h1
-rw-r--r--drivers/sound/lowlevel/ChangeLog.awe206
-rw-r--r--drivers/sound/lowlevel/Config.in11
-rw-r--r--drivers/sound/lowlevel/README18
-rw-r--r--drivers/sound/lowlevel/README.awe205
-rw-r--r--drivers/sound/lowlevel/awe_compat-fbsd.h173
-rw-r--r--drivers/sound/lowlevel/awe_compat-linux.h248
-rw-r--r--drivers/sound/lowlevel/awe_compat.h230
-rw-r--r--drivers/sound/lowlevel/awe_config.h115
-rw-r--r--drivers/sound/lowlevel/awe_hw.h21
-rw-r--r--drivers/sound/lowlevel/awe_version.h34
-rw-r--r--drivers/sound/lowlevel/awe_voice.h490
-rw-r--r--drivers/sound/lowlevel/awe_wave.c2538
-rw-r--r--drivers/sound/mad16.c53
-rw-r--r--drivers/sound/midibuf.c14
-rw-r--r--drivers/sound/msnd.h4
-rw-r--r--drivers/sound/msnd_pinnacle.c218
-rw-r--r--drivers/sound/opl3sa.c1
-rw-r--r--drivers/sound/opl3sa2.c649
-rw-r--r--drivers/sound/pas2_card.c36
-rw-r--r--drivers/sound/pas2_midi.c160
-rw-r--r--drivers/sound/pas2_pcm.c2
-rw-r--r--drivers/sound/pss.c4
-rw-r--r--drivers/sound/sb.h17
-rw-r--r--drivers/sound/sb_audio.c306
-rw-r--r--drivers/sound/sb_card.c2
-rw-r--r--drivers/sound/sb_common.c289
-rw-r--r--drivers/sound/sb_ess.c1732
-rw-r--r--drivers/sound/sb_ess.h34
-rw-r--r--drivers/sound/sb_mixer.c335
-rw-r--r--drivers/sound/sb_mixer.h243
-rw-r--r--drivers/sound/sequencer.c6
-rw-r--r--drivers/sound/skeleton.c224
-rw-r--r--drivers/sound/softoss_rs.c2
-rw-r--r--drivers/sound/sonicvibes.c60
-rw-r--r--drivers/sound/sound_calls.h36
-rw-r--r--drivers/sound/sound_config.h2
-rw-r--r--drivers/sound/sound_core.c122
-rw-r--r--drivers/sound/sound_firmware.c1
-rw-r--r--drivers/sound/sound_syms.c3
-rw-r--r--drivers/sound/soundcard.c9
-rw-r--r--drivers/sound/trix.c1
-rw-r--r--drivers/sound/vidc.c72
-rw-r--r--drivers/sound/vidc.h20
-rw-r--r--drivers/sound/vidc_audio.c101
-rw-r--r--drivers/sound/vidc_fill.S79
-rw-r--r--drivers/sound/vidc_mixer.c6
-rw-r--r--drivers/sound/vidc_synth.c54
-rw-r--r--drivers/sound/waveartist.c1956
-rw-r--r--drivers/sound/waveartist.h68
-rw-r--r--drivers/sound/wavfront.c2588
-rw-r--r--drivers/sound/wf_midi.c641
-rw-r--r--drivers/video/Config.in30
-rw-r--r--drivers/video/Makefile10
-rw-r--r--drivers/video/amifb.c24
-rw-r--r--drivers/video/atafb.c21
-rw-r--r--drivers/video/atyfb.c179
-rw-r--r--drivers/video/cgsixfb.c14
-rw-r--r--drivers/video/chipsfb.c127
-rw-r--r--drivers/video/clgenfb.c10
-rw-r--r--drivers/video/controlfb.c517
-rw-r--r--drivers/video/controlfb.h46
-rw-r--r--drivers/video/creatorfb.c78
-rw-r--r--drivers/video/cvisionppc.h51
-rw-r--r--drivers/video/cvppcfb.c606
-rw-r--r--drivers/video/cyberfb.c37
-rw-r--r--drivers/video/cyberfb.h2
-rw-r--r--drivers/video/fbcon-cfb8.c16
-rw-r--r--drivers/video/fbcon-iplan2p2.c4
-rw-r--r--drivers/video/fbcon-iplan2p4.c4
-rw-r--r--drivers/video/fbcon-iplan2p8.c4
-rw-r--r--drivers/video/fbcon.c229
-rw-r--r--drivers/video/fbmem.c16
-rw-r--r--drivers/video/font_sun12x22.c11268
-rw-r--r--drivers/video/imsttfb.c662
-rw-r--r--drivers/video/macfb.c165
-rw-r--r--drivers/video/matroxfb.c1428
-rw-r--r--drivers/video/mdacon.c2
-rw-r--r--drivers/video/offb.c141
-rw-r--r--drivers/video/pm2fb.c1494
-rw-r--r--drivers/video/pm2fb.h181
-rw-r--r--drivers/video/retz3fb.c59
-rw-r--r--drivers/video/sbusfb.c24
-rw-r--r--drivers/video/tgafb.c52
-rw-r--r--drivers/video/virgefb.c47
414 files changed, 64648 insertions, 27399 deletions
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index a92320305..8cf2614b9 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -1039,7 +1039,7 @@ static void fd_rwsec_done(int status)
static void fd_times_out(unsigned long dummy)
{
SET_IRQ_HANDLER(NULL);
- /* If the timeout occured while the readtrack_check timer was
+ /* If the timeout occurred while the readtrack_check timer was
* active, we need to cancel it, else bad things will happen */
del_timer( &readtrack_timer );
FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
@@ -1090,7 +1090,7 @@ static void finish_fdc_done(int dummy)
NeedSeek = 0;
if ((timer_active & (1 << FLOPPY_TIMER)) &&
- timer_table[FLOPPY_TIMER].expires < jiffies + 5)
+ time_after(jiffies + 5, timer_table[FLOPPY_TIMER].expires))
/* If the check for a disk change is done too early after this
* last seek command, the WP bit still reads wrong :-((
*/
@@ -1424,7 +1424,7 @@ static int fd_test_drive_present(int drive)
FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_RESTORE | FDC1772CMDADD_H | FDC1772STEP_6);
/*printk("fd_test_drive_present: Going into timeout loop\n"); */
- for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; jiffies < timeout;) {
+ for (ok = 0, timeout = jiffies + 2 * HZ + HZ / 2; time_before(jiffies, timeout);) {
/* What does this piece of atariism do? - query for an interrupt? */
/* if (!(mfp.par_dt_reg & 0x20))
break; */
diff --git a/drivers/acorn/block/ide-ics.c b/drivers/acorn/block/ide-ics.c
index 188206d3a..17bc5e6fd 100644
--- a/drivers/acorn/block/ide-ics.c
+++ b/drivers/acorn/block/ide-ics.c
@@ -27,6 +27,7 @@
#define ICS_IDENT_OFFSET 0x8a0
+#define ICS_ARCIN_V5_INTRSTAT 0x000
#define ICS_ARCIN_V5_INTROFFSET 0x001
#define ICS_ARCIN_V5_IDEOFFSET 0xa00
#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0
@@ -34,9 +35,11 @@
#define ICS_ARCIN_V6_IDEOFFSET_1 0x800
#define ICS_ARCIN_V6_INTROFFSET_1 0x880
+#define ICS_ARCIN_V6_INTRSTAT_1 0x8a4
#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0
#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00
#define ICS_ARCIN_V6_INTROFFSET_2 0xc80
+#define ICS_ARCIN_V6_INTRSTAT_2 0xca4
#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0
#define ICS_ARCIN_V6_IDESTEPPING 4
@@ -199,6 +202,8 @@ static inline void icside_register (struct expansion_card *ec, int index)
case ics_if_arcin_v5:
port = ecard_address (ec, ECARD_MEMC, 0);
+ ec->irqaddr = ioaddr(port + ICS_ARCIN_V5_INTRSTAT);
+ ec->irqmask = 1;
ec->irq_data = (void *)port;
ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5;
@@ -210,10 +215,13 @@ static inline void icside_register (struct expansion_card *ec, int index)
port + ICS_ARCIN_V5_IDEALTOFFSET,
ICS_ARCIN_V5_IDESTEPPING,
ec->irq);
+ result[index][1] = -1;
break;
case ics_if_arcin_v6:
port = ecard_address (ec, ECARD_IOC, ECARD_FAST);
+ ec->irqaddr = ioaddr(port + ICS_ARCIN_V6_INTRSTAT_1);
+ ec->irqmask = 1;
ec->irq_data = (void *)port;
ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
diff --git a/drivers/acorn/char/Config.in b/drivers/acorn/char/Config.in
index cbd70732d..ede0a8266 100644
--- a/drivers/acorn/char/Config.in
+++ b/drivers/acorn/char/Config.in
@@ -2,3 +2,14 @@ if [ "$CONFIG_SERIAL" != "n" ]; then
tristate ' Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL
fi
+
+if [ "$CONFIG_MOUSE" = "y" ]; then
+ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+ if [ "$CONFIG_ARCH_RPC" != "y" ]; then
+ define_bool CONFIG_KBDMOUSE y
+ else
+ define_bool CONFIG_RPCMOUSE y
+ fi
+ fi
+fi
+
diff --git a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile
index ffc01825f..ecbbfe90c 100644
--- a/drivers/acorn/char/Makefile
+++ b/drivers/acorn/char/Makefile
@@ -13,6 +13,19 @@ L_TARGET := acorn-char.a
M_OBJS :=
L_OBJS :=
+ifeq ($(MACHINE),rpc)
+ MOUSE_OBJS += mouse_rpc.o
+ L_OBJS += keyb_ps2.o
+endif
+
+ifeq ($(CONFIG_MOUSE),y)
+ LX_OBJS += $(MOUSE_OBJS)
+else
+ ifeq ($(CONFIG_MOUSE),m)
+ MX_OBJS += $(MOUSE_OBJS)
+ endif
+endif
+
ifeq ($(CONFIG_ATOMWIDE_SERIAL),y)
L_OBJS += serial-atomwide.o
else
diff --git a/drivers/acorn/char/keyb_ps2.c b/drivers/acorn/char/keyb_ps2.c
new file mode 100644
index 000000000..c3ef33363
--- /dev/null
+++ b/drivers/acorn/char/keyb_ps2.c
@@ -0,0 +1,355 @@
+/*
+ * linux/arch/arm/drivers/block/keyb_ps2.c
+ *
+ * Keyboard driver for RPC ARM Linux.
+ *
+ * Note!!! This driver talks directly to the keyboard.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/kbd_ll.h>
+#include <linux/init.h>
+
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+extern void kbd_reset_kdown(void);
+int kbd_read_mask;
+
+#define IRQ_KEYBOARDRX 15
+
+#define VERSION 100
+
+#define KBD_REPORT_ERR
+#define KBD_REPORT_UNKN
+
+#define KBD_ESCAPEE0 0xe0 /* in */
+#define KBD_ESCAPEE1 0xe1 /* in */
+
+#define ESCE0(x) (0xe000|(x))
+#define ESCE1(x) (0xe100|(x))
+
+#define KBD_BAT 0xaa /* in */
+#define KBD_SETLEDS 0xed /* out */
+#define KBD_ECHO 0xee /* in/out */
+#define KBD_BREAK 0xf0 /* in */
+#define KBD_TYPRATEDLY 0xf3 /* out */
+#define KBD_SCANENABLE 0xf4 /* out */
+#define KBD_DEFDISABLE 0xf5 /* out */
+#define KBD_DEFAULT 0xf6 /* out */
+#define KBD_ACK 0xfa /* in */
+#define KBD_DIAGFAIL 0xfd /* in */
+#define KBD_RESEND 0xfe /* in/out */
+#define KBD_RESET 0xff /* out */
+
+#define CODE_BREAK 1
+#define CODE_ESCAPEE0 2
+#define CODE_ESCAPEE1 4
+#define CODE_ESCAPE12 8
+
+#define K_NONE 0x7f
+#define K_ESC 0x00
+#define K_F1 0x01
+#define K_F2 0x02
+#define K_F3 0x03
+#define K_F4 0x04
+#define K_F5 0x05
+#define K_F6 0x06
+#define K_F7 0x07
+#define K_F8 0x08
+#define K_F9 0x09
+#define K_F10 0x0a
+#define K_F11 0x0b
+#define K_F12 0x0c
+#define K_PRNT 0x0d
+#define K_SCRL 0x0e
+#define K_BRK 0x0f
+#define K_AGR 0x10
+#define K_1 0x11
+#define K_2 0x12
+#define K_3 0x13
+#define K_4 0x14
+#define K_5 0x15
+#define K_6 0x16
+#define K_7 0x17
+#define K_8 0x18
+#define K_9 0x19
+#define K_0 0x1a
+#define K_MINS 0x1b
+#define K_EQLS 0x1c
+#define K_BKSP 0x1e
+#define K_INS 0x1f
+#define K_HOME 0x20
+#define K_PGUP 0x21
+#define K_NUML 0x22
+#define KP_SLH 0x23
+#define KP_STR 0x24
+#define KP_MNS 0x3a
+#define K_TAB 0x26
+#define K_Q 0x27
+#define K_W 0x28
+#define K_E 0x29
+#define K_R 0x2a
+#define K_T 0x2b
+#define K_Y 0x2c
+#define K_U 0x2d
+#define K_I 0x2e
+#define K_O 0x2f
+#define K_P 0x30
+#define K_LSBK 0x31
+#define K_RSBK 0x32
+#define K_ENTR 0x47
+#define K_DEL 0x34
+#define K_END 0x35
+#define K_PGDN 0x36
+#define KP_7 0x37
+#define KP_8 0x38
+#define KP_9 0x39
+#define KP_PLS 0x4b
+#define K_CAPS 0x5d
+#define K_A 0x3c
+#define K_S 0x3d
+#define K_D 0x3e
+#define K_F 0x3f
+#define K_G 0x40
+#define K_H 0x41
+#define K_J 0x42
+#define K_K 0x43
+#define K_L 0x44
+#define K_SEMI 0x45
+#define K_SQOT 0x46
+#define K_HASH 0x1d
+#define KP_4 0x48
+#define KP_5 0x49
+#define KP_6 0x4a
+#define K_LSFT 0x4c
+#define K_BSLH 0x33
+#define K_Z 0x4e
+#define K_X 0x4f
+#define K_C 0x50
+#define K_V 0x51
+#define K_B 0x52
+#define K_N 0x53
+#define K_M 0x54
+#define K_COMA 0x55
+#define K_DOT 0x56
+#define K_FSLH 0x57
+#define K_RSFT 0x58
+#define K_UP 0x59
+#define KP_1 0x5a
+#define KP_2 0x5b
+#define KP_3 0x5c
+#define KP_ENT 0x67
+#define K_LCTL 0x3b
+#define K_LALT 0x5e
+#define K_SPCE 0x5f
+#define K_RALT 0x60
+#define K_RCTL 0x61
+#define K_LEFT 0x62
+#define K_DOWN 0x63
+#define K_RGHT 0x64
+#define KP_0 0x65
+#define KP_DOT 0x66
+
+static unsigned char keycode_translate[256] =
+{
+/* 00 */ K_NONE, K_F9 , K_NONE, K_F5 , K_F3 , K_F1 , K_F2 , K_F12 ,
+/* 08 */ K_NONE, K_F10 , K_F8 , K_F6 , K_F4 , K_TAB , K_AGR , K_NONE,
+/* 10 */ K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q , K_1 , K_NONE,
+/* 18 */ K_NONE, K_NONE, K_Z , K_S , K_A , K_W , K_2 , K_NONE,
+/* 20 */ K_NONE, K_C , K_X , K_D , K_E , K_4 , K_3 , K_NONE,
+/* 28 */ K_NONE, K_SPCE, K_V , K_F , K_T , K_R , K_5 , K_NONE,
+/* 30 */ K_NONE, K_N , K_B , K_H , K_G , K_Y , K_6 , K_NONE,
+/* 38 */ K_NONE, K_NONE, K_M , K_J , K_U , K_7 , K_8 , K_NONE,
+/* 40 */ K_NONE, K_COMA, K_K , K_I , K_O , K_0 , K_9 , K_NONE,
+/* 48 */ K_NONE, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE,
+/* 50 */ K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
+/* 58 */ K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_HASH, K_NONE, K_NONE,
+/* 60 */ K_NONE, K_BSLH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
+/* 68 */ K_NONE, KP_1 , K_NONE, KP_4 , KP_7 , K_NONE, K_NONE, K_NONE,
+/* 70 */ KP_0 , KP_DOT, KP_2 , KP_5 , KP_6 , KP_8 , K_ESC , K_NUML,
+/* 78 */ K_F11 , KP_PLS, KP_3 , KP_MNS, KP_STR, KP_9 , K_SCRL, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_F7 , K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+ K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE
+};
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char ps2kbd_sysrq_xlate[] =
+{
+ 27, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ '`', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', '0', '-', '=', '£', 127, 0,
+ 0, 0, 0, '/', '*', '#', 9, 'q',
+ 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
+ 'p', '[', ']', '\\', 22, 23, 25, '7',
+ '8', '9', '-', 0, 'a', 's', 'd', 'f',
+ 'g', 'h', 'j', 'k', 'l', ';', '\'', 13,
+ '4', '5', '6', '+', 0, 0, 'z', 'x',
+ 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
+ 0, 0, '1', '2', '3', 0, 0, ' ',
+ 0, 0, 0, 0, 0, '0', '.', 10,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+#endif
+
+int ps2kbd_pretranslate(unsigned char scancode)
+{
+ return 1;
+}
+
+int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *uf_p)
+{
+ *uf_p = scancode & 0200;
+ *keycode_p = scancode & 0x7f;
+ return 1;
+}
+
+static void ps2kbd_key(unsigned int keycode, unsigned int up_flag)
+{
+ handle_scancode(keycode + (up_flag ? 0x80 : 0));
+}
+
+static inline void ps2kbd_sendbyte(unsigned char val)
+{
+ while(!(inb(IOMD_KCTRL) & (1 << 7)));
+ outb(val, IOMD_KARTTX);
+}
+
+static unsigned char status;
+static unsigned char ncodes;
+static unsigned char bi;
+static unsigned char buffer[4];
+
+static inline void ps2kbd_reset(void)
+{
+ status = 0;
+ kbd_reset_kdown();
+}
+
+static void handle_rawcode(int keyval)
+{
+ int keysym;
+
+ if (keyval > 0x83) {
+ switch (keyval) {
+ case KBD_ESCAPEE0:
+ ncodes = 2;
+ bi = 0;
+ break;
+ case KBD_ESCAPEE1:
+ ncodes = 3;
+ bi = 0;
+ break;
+ case KBD_BREAK:
+ status |= CODE_BREAK;
+ default:
+ return;
+ }
+ }
+
+ if (ncodes) {
+ buffer[bi++] = keyval;
+ ncodes -= 1;
+ if (ncodes)
+ return;
+ keysym = K_NONE;
+ switch (buffer[0] << 8 | buffer[1]) {
+ case ESCE0(0x11): keysym = K_RALT; break;
+ case ESCE0(0x14): keysym = K_RCTL; break;
+ case ESCE0(0x4a): keysym = KP_SLH; break;
+ case ESCE0(0x5a): keysym = KP_ENT; break;
+ case ESCE0(0x69): keysym = K_END; break;
+ case ESCE0(0x6b): keysym = K_LEFT; break;
+ case ESCE0(0x6c): keysym = K_HOME; break;
+ case ESCE0(0x70): keysym = K_INS; break;
+ case ESCE0(0x71): keysym = K_DEL; break;
+ case ESCE0(0x72): keysym = K_DOWN; break;
+ case ESCE0(0x74): keysym = K_RGHT; break;
+ case ESCE0(0x75): keysym = K_UP; break;
+ case ESCE0(0x7a): keysym = K_PGDN; break;
+ case ESCE0(0x7c): keysym = K_PRNT; break;
+ case ESCE0(0x7d): keysym = K_PGUP; break;
+ case ESCE1(0x14):
+ if (buffer[2] == 0x77)
+ keysym = K_BRK;
+ break;
+ case ESCE0(0x12): /* ignore escaped shift key */
+ status = 0;
+ return;
+ }
+ } else {
+ bi = 0;
+ keysym = keycode_translate[keyval];
+ }
+
+ if (keysym != K_NONE)
+ ps2kbd_key(keysym, status & CODE_BREAK);
+ status = 0;
+}
+
+void ps2kbd_leds(unsigned int leds)
+{
+ ps2kbd_sendbyte(KBD_SETLEDS);
+ ps2kbd_sendbyte(leds);
+ ps2kbd_sendbyte(KBD_SCANENABLE);
+}
+
+static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs)
+{
+ kbd_pt_regs = regs;
+
+ while (inb(IOMD_KCTRL) & (1 << 5))
+ handle_rawcode(inb(IOMD_KARTRX));
+ mark_bh(KEYBOARD_BH);
+}
+
+static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+__initfunc(int ps2kbd_init_hw(void))
+{
+ unsigned long flags;
+
+ save_flags_cli (flags);
+ if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0)
+ panic("Could not allocate keyboard receive IRQ!");
+ if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0)
+ panic("Could not allocate keyboard transmit IRQ!");
+ disable_irq (IRQ_KEYBOARDTX);
+ (void)IOMD_KARTRX;
+ restore_flags (flags);
+
+ printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100);
+ return 0;
+}
+
diff --git a/drivers/acorn/char/mouse_rpc.c b/drivers/acorn/char/mouse_rpc.c
new file mode 100644
index 000000000..a5c2b2bff
--- /dev/null
+++ b/drivers/acorn/char/mouse_rpc.c
@@ -0,0 +1,86 @@
+/*
+ * linux/drivers/char/rpcmouse.c
+ *
+ * Copyright (C) 1996-1998 Russell King
+ *
+ * This handles the Acorn RiscPCs mouse. We basically have a couple
+ * of hardware registers that track the sensor count for the X-Y movement
+ * and another register holding the button state. On every VSYNC interrupt
+ * we read the complete state and then work out if something has changed.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "../../char/mouse.h"
+
+static short old_x, old_y, old_b;
+static int mousedev;
+
+void
+mouse_rpc_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ short x, y, dx, dy;
+ int buttons;
+
+ x = (short)inl(IOMD_MOUSEX);
+ y = (short)inl(IOMD_MOUSEY);
+ buttons = (inl (0x800C4000) >> 4) & 7;
+
+ dx = x - old_x;
+ old_x = x;
+ dy = y - old_y;
+ old_y = y;
+
+ if (dx || dy || buttons != old_b) {
+ busmouse_add_movementbuttons(mousedev, dx, dy, buttons);
+ old_b = buttons;
+ }
+}
+
+static struct busmouse rpcmouse = {
+ 6, "arcmouse", NULL, NULL, 7
+};
+
+int
+mouse_rpc_init(void)
+{
+ mousedev = register_busmouse(&rpcmouse);
+
+ if (mousedev < 0)
+ printk("rpcmouse: could not register mouse driver\n");
+ else {
+ old_x = (short)inl(IOMD_MOUSEX);
+ old_y = (short)inl(IOMD_MOUSEY);
+ old_b = (inl (0x800C4000) >> 4) & 7;
+ if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) {
+ printk("rpcmouse: unable to allocate VSYNC interrupt\n");
+ unregister_busmouse(mousedev);
+ mousedev = -1;
+ }
+ }
+
+ return mousedev >= 0 ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+int
+init_module(void)
+{
+ return mouse_rpc_init();
+}
+
+int
+cleanup_module(void)
+{
+ if (mousedev >= 0) {
+ unregister_busmouse(mousedev);
+ free_irq(IRQ_VSYNCPULSE, &mousedev);
+ }
+}
+#endif
diff --git a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c
index f57cb7ffe..1d2283f3d 100644
--- a/drivers/acorn/net/ether1.c
+++ b/drivers/acorn/net/ether1.c
@@ -519,7 +519,7 @@ ether1_init_for_open (struct device *dev)
/* 586 should now unset iscp.busy */
i = jiffies + HZ/2;
while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
- if (jiffies > i) {
+ if (time_after(jiffies, i)) {
printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
return 1;
}
@@ -529,7 +529,7 @@ ether1_init_for_open (struct device *dev)
i += HZ/10;
while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
- if (jiffies > i)
+ if (time_after(jiffies, i))
break;
}
@@ -546,7 +546,7 @@ ether1_init_for_open (struct device *dev)
i += HZ/10;
while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
- if (jiffies > i)
+ if (time_after(jiffies, i))
break;
}
@@ -563,7 +563,7 @@ ether1_init_for_open (struct device *dev)
i += HZ/10;
while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
- if (jiffies > i)
+ if (time_after(jiffies, i))
break;
}
@@ -580,7 +580,7 @@ ether1_init_for_open (struct device *dev)
i += HZ;
while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
& STAT_COMPLETE) == 0) {
- if (jiffies > i)
+ if (time_after(jiffies, i))
break;
}
diff --git a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c
index 1add27498..4f88f6bb4 100644
--- a/drivers/acorn/net/etherh.c
+++ b/drivers/acorn/net/etherh.c
@@ -186,7 +186,7 @@ etherh_block_output (struct device *dev, int count, const unsigned char *buf, in
if (ei_status.dmaing) {
printk ("%s: DMAing conflict in etherh_block_input: "
- " DMAstat %d irqlock %d intr %d\n", dev->name,
+ " DMAstat %d irqlock %d intr %ld\n", dev->name,
ei_status.dmaing, ei_status.irqlock, dev->interrupt);
return;
}
@@ -246,7 +246,7 @@ etherh_block_input (struct device *dev, int count, struct sk_buff *skb, int ring
if (ei_status.dmaing) {
printk ("%s: DMAing conflict in etherh_block_input: "
- " DMAstat %d irqlock %d intr %d\n", dev->name,
+ " DMAstat %d irqlock %d intr %ld\n", dev->name,
ei_status.dmaing, ei_status.irqlock, dev->interrupt);
return;
}
@@ -288,7 +288,7 @@ etherh_get_header (struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
if (ei_status.dmaing) {
printk ("%s: DMAing conflict in etherh_get_header: "
- " DMAstat %d irqlock %d intr %d\n", dev->name,
+ " DMAstat %d irqlock %d intr %ld\n", dev->name,
ei_status.dmaing, ei_status.irqlock, dev->interrupt);
return;
}
@@ -469,9 +469,9 @@ static void etherh_initdev (ecard_t *ec, struct device *dev)
ecard_claim (ec);
dev->irq = ec->irq;
- dev->mem_end = ec->cld.product;
+ dev->mem_end = ec->cid.product;
- switch (ec->cld.product) {
+ switch (ec->cid.product) {
case PROD_I3_ETHERLAN500:
dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
index a203bc5c2..50ec36436 100644
--- a/drivers/acorn/scsi/acornscsi.c
+++ b/drivers/acorn/scsi/acornscsi.c
@@ -148,10 +148,11 @@
#include "../../scsi/hosts.h"
#include "../../scsi/constants.h"
#include "acornscsi.h"
+#include "msgqueue.h"
#define VER_MAJOR 2
#define VER_MINOR 0
-#define VER_PATCH 5
+#define VER_PATCH 6
#ifndef ABORT_TAG
#define ABORT_TAG 0xd
@@ -177,6 +178,8 @@
#define DMAC_WRITE (MODECON_WRITE)
#define INIT_SBICDMA (CTRL_DMABURST)
+#define scsi_xferred have_data_in
+
/*
* Size of on-board DMA buffer
*/
@@ -259,6 +262,29 @@ unsigned int dmac_address (unsigned int io_port)
dmac_read (io_port, TXADRMD) << 8 |
dmac_read (io_port, TXADRLO);
}
+
+static
+void acornscsi_dumpdma (AS_Host *host, char *where)
+{
+ unsigned int mode, addr, len;
+
+ mode = dmac_read (host->dma.io_port, MODECON);
+ addr = dmac_address (host->dma.io_port);
+ len = dmac_read (host->dma.io_port, TXCNTHI) << 8 |
+ dmac_read (host->dma.io_port, TXCNTLO);
+
+ printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
+ host->host->host_no, where,
+ mode, addr, (len + 1) & 0xffff,
+ dmac_read (host->dma.io_port, MASKREG));
+
+ printk ("DMA @%06x, ", host->dma.start_addr);
+ printk ("BH @%p +%04x, ", host->scsi.SCp.ptr,
+ host->scsi.SCp.this_residual);
+ printk ("DT @+%04x ST @+%04x", host->dma.transferred,
+ host->scsi.SCp.scsi_xferred);
+ printk ("\n");
+}
#endif
static
@@ -297,7 +323,7 @@ acornscsi_csdelay (unsigned int cs)
save_flags (flags);
sti ();
- while (jiffies < target_jiffies) barrier();
+ while (time_before(jiffies, target_jiffies)) barrier();
restore_flags (flags);
}
@@ -345,15 +371,13 @@ void acornscsi_resetcard (AS_Host *host)
host->card.page_reg = 0x40;
outb (host->card.page_reg, host->card.io_page);
-#ifdef USE_DMAC
/* setup dmac - uPC71071 */
- dmac_write (host->dma.io_port, INIT, 0);
- dmac_write (host->dma.io_port, INIT, INIT_8BIT);
- dmac_write (host->dma.io_port, CHANNEL, CHANNEL_0);
- dmac_write (host->dma.io_port, DEVCON0, INIT_DEVCON0);
- dmac_write (host->dma.io_port, DEVCON1, INIT_DEVCON1);
-#else
- dmac_write (host->dma.io_port, INIT, 0);
+ dmac_write(host->dma.io_port, INIT, 0);
+#ifdef USE_DMAC
+ dmac_write(host->dma.io_port, INIT, INIT_8BIT);
+ dmac_write(host->dma.io_port, CHANNEL, CHANNEL_0);
+ dmac_write(host->dma.io_port, DEVCON0, INIT_DEVCON0);
+ dmac_write(host->dma.io_port, DEVCON1, INIT_DEVCON1);
#endif
host->SCpnt = NULL;
@@ -517,31 +541,6 @@ char acornscsi_target (AS_Host *host)
return 'H';
}
-#ifdef USE_DMAC
-static
-void acornscsi_dumpdma (AS_Host *host, char *where)
-{
- unsigned int mode, addr, len;
-
- mode = dmac_read (host->dma.io_port, MODECON);
- addr = dmac_address (host->dma.io_port);
- len = dmac_read (host->dma.io_port, TXCNTHI) << 8 |
- dmac_read (host->dma.io_port, TXCNTLO);
-
- printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
- host->host->host_no, where,
- mode, addr, (len + 1) & 0xffff,
- dmac_read (host->dma.io_port, MASKREG));
-
- printk ("DMA @%06x, ", host->dma.start_addr);
- printk ("BH @%p +%04x, ", host->scsi.SCp.ptr,
- host->scsi.SCp.this_residual);
- printk ("DT @+%04x ST @+%04x", host->dma.transferred,
- host->scsi.SCp.have_data_in);
- printk ("\n");
-}
-#endif
-
/*
* Prototype: cmdtype_t acornscsi_cmdtype (int command)
* Purpose : differentiate READ from WRITE from other commands
@@ -1051,7 +1050,7 @@ void acornscsi_dma_cleanup (AS_Host *host)
host->dma.xfer_setup = 0;
#if (DEBUG & DEBUG_DMA)
- DBG(host->SCpnt, acornscsi_dumpdma (host, "clup"));
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi"));
#endif
/*
@@ -1068,6 +1067,9 @@ void acornscsi_dma_cleanup (AS_Host *host)
* Update SCSI pointers
*/
acornscsi_data_updateptr (host, &host->scsi.SCp, transferred);
+#if (DEBUG & DEBUG_DMA)
+ DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
+#endif
}
}
@@ -1193,15 +1195,15 @@ void acornscsi_dma_adjust (AS_Host *host)
/*
* Calculate correct DMA address - DMA is ahead of SCSI bus while
* writing.
- * host->scsi.SCp.have_data_in is the number of bytes
+ * host->scsi.SCp.scsi_xferred is the number of bytes
* actually transferred to/from the SCSI bus.
* host->dma.transferred is the number of bytes transferred
* over DMA since host->dma.start_addr was last set.
*
- * real_dma_addr = host->dma.start_addr + host->scsi.SCp.have_data_in
+ * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred
* - host->dma.transferred
*/
- transferred = host->scsi.SCp.have_data_in - host->dma.transferred;
+ transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
if (transferred < 0)
printk ("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
host->host->host_no, acornscsi_target (host), transferred);
@@ -1259,8 +1261,8 @@ static
void acornscsi_sendmessage (AS_Host *host)
{
unsigned int message_length = msgqueue_msglength (&host->scsi.msgs);
- int msglen;
- char *msg;
+ int msgnr;
+ struct message *msg;
#if (DEBUG & DEBUG_MESSAGES)
printk ("scsi%d.%c: sending message ",
@@ -1280,12 +1282,12 @@ void acornscsi_sendmessage (AS_Host *host)
case 1:
acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
- msg = msgqueue_getnextmsg (&host->scsi.msgs, &msglen);
+ msg = msgqueue_getmsg(&host->scsi.msgs, 0);
while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
- sbic_arm_write (host->scsi.io_port, DATA, msg[0]);
- host->scsi.last_message = msg[0];
+ sbic_arm_write (host->scsi.io_port, DATA, msg->msg[0]);
+ host->scsi.last_message = msg->msg[0];
#if (DEBUG & DEBUG_MESSAGES)
- print_msg (msg);
+ print_msg(msg->msg);
#endif
break;
@@ -1303,21 +1305,22 @@ void acornscsi_sendmessage (AS_Host *host)
sbic_arm_writenext (host->scsi.io_port, message_length);
acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
- while ((msg = msgqueue_getnextmsg (&host->scsi.msgs, &msglen)) != NULL) {
+ msgnr = 0;
+ while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
unsigned int asr, i;
#if (DEBUG & DEBUG_MESSAGES)
print_msg (msg);
#endif
- for (i = 0; i < msglen;) {
+ for (i = 0; i < msg->length;) {
asr = sbic_arm_read (host->scsi.io_port, ASR);
if (asr & ASR_DBR)
- sbic_arm_write (host->scsi.io_port, DATA, msg[i++]);
+ sbic_arm_write (host->scsi.io_port, DATA, msg->msg[i++]);
if (asr & ASR_INT)
break;
}
- host->scsi.last_message = msg[0];
- if (msg[0] == EXTENDED_MESSAGE)
- host->scsi.last_message |= msg[2] << 8;
+ host->scsi.last_message = msg->msg[0];
+ if (msg->msg[0] == EXTENDED_MESSAGE)
+ host->scsi.last_message |= msg->msg[2] << 8;
if (asr & ASR_INT)
break;
}
@@ -1401,10 +1404,10 @@ void acornscsi_message (AS_Host *host)
} while (msgidx < msglen);
#if (DEBUG & DEBUG_MESSAGES)
- printk (KERN_DEBUG "scsi%d.%c: message in: ",
+ printk("scsi%d.%c: message in: ",
host->host->host_no, acornscsi_target (host));
- print_msg (message);
- printk ("\n");
+ print_msg(message);
+ printk("\n");
#endif
if (host->scsi.phase == PHASE_RECONNECTED) {
@@ -1424,9 +1427,11 @@ void acornscsi_message (AS_Host *host)
case ABORT:
case ABORT_TAG:
case COMMAND_COMPLETE:
- if (host->scsi.phase != PHASE_STATUSIN)
- printk (KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
+ if (host->scsi.phase != PHASE_STATUSIN) {
+ printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
host->host->host_no, acornscsi_target (host));
+ acornscsi_dumplog(host, host->SCpnt->target);
+ }
host->scsi.phase = PHASE_DONE;
host->scsi.SCp.Message = message[0];
break;
@@ -1594,7 +1599,7 @@ void acornscsi_message (AS_Host *host)
*/
if (0) {
#if (DEBUG & DEBUG_LINK)
- printk (KERN_DEBUG "scsi%d.%c: lun %d tag %d linked command complete\n",
+ printk("scsi%d.%c: lun %d tag %d linked command complete\n",
host->host->host_no, acornscsi_target(host), host->SCpnt->tag);
#endif
/*
@@ -1704,7 +1709,7 @@ int acornscsi_starttransfer (AS_Host *host)
return 0;
}
- residual = host->SCpnt->request_bufflen - host->scsi.SCp.have_data_in;
+ residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
sbic_arm_writenext (host->scsi.io_port, residual >> 16);
@@ -1833,7 +1838,7 @@ int acornscsi_reconnect_finish (AS_Host *host)
printk ("\n");
#endif
- host->dma.transferred = host->scsi.SCp.have_data_in;
+ host->dma.transferred = host->scsi.SCp.scsi_xferred;
return host->SCpnt != NULL;
}
@@ -1935,7 +1940,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
/* BUS FREE -> SELECTION */
host->scsi.phase = PHASE_CONNECTED;
msgqueue_flush (&host->scsi.msgs);
- host->dma.transferred = host->scsi.SCp.have_data_in;
+ host->dma.transferred = host->scsi.SCp.scsi_xferred;
/* 33C93 gives next interrupt indicating bus phase */
asr = sbic_arm_read (host->scsi.io_port, ASR);
if (!(asr & ASR_INT))
@@ -2178,7 +2183,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
case 0x4b: /* -> PHASE_STATUSIN */
case 0x1b: /* -> PHASE_STATUSIN */
/* DATA IN -> STATUS */
- host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
acornscsi_sbic_xfcount (host);
acornscsi_dma_stop (host);
acornscsi_readstatusbyte (host);
@@ -2188,7 +2193,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
case 0x1e: /* -> PHASE_MSGOUT */
case 0x4e: /* -> PHASE_MSGOUT */
/* DATA IN -> MESSAGE OUT */
- host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
acornscsi_sbic_xfcount (host);
acornscsi_dma_stop (host);
acornscsi_sendmessage (host);
@@ -2197,7 +2202,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
case 0x1f: /* message in */
case 0x4f: /* message in */
/* DATA IN -> MESSAGE IN */
- host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
acornscsi_sbic_xfcount (host);
acornscsi_dma_stop (host);
acornscsi_message (host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */
@@ -2223,7 +2228,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
case 0x4b: /* -> PHASE_STATUSIN */
case 0x1b: /* -> PHASE_STATUSIN */
/* DATA OUT -> STATUS */
- host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
acornscsi_sbic_xfcount (host);
acornscsi_dma_stop (host);
acornscsi_dma_adjust (host);
@@ -2234,7 +2239,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
case 0x1e: /* -> PHASE_MSGOUT */
case 0x4e: /* -> PHASE_MSGOUT */
/* DATA OUT -> MESSAGE OUT */
- host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
acornscsi_sbic_xfcount (host);
acornscsi_dma_stop (host);
acornscsi_dma_adjust (host);
@@ -2244,7 +2249,7 @@ intr_ret_t acornscsi_sbicintr (AS_Host *host, int in_irq)
case 0x1f: /* message in */
case 0x4f: /* message in */
/* DATA OUT -> MESSAGE IN */
- host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+ host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
acornscsi_sbic_xfcount (host);
acornscsi_dma_stop (host);
acornscsi_dma_adjust (host);
@@ -2426,7 +2431,7 @@ int acornscsi_queuecmd (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
SCpnt->tag = 0;
SCpnt->SCp.phase = (int)acornscsi_datadirection (SCpnt->cmnd[0]);
SCpnt->SCp.sent_command = 0;
- SCpnt->SCp.have_data_in = 0;
+ SCpnt->SCp.scsi_xferred = 0;
SCpnt->SCp.Status = 0;
SCpnt->SCp.Message = 0;
@@ -2592,7 +2597,7 @@ int acornscsi_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
SCpnt->result = DID_RESET << 16;
SCpnt->scsi_done (SCpnt);
}
-while (1);
+
return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
}
@@ -2658,6 +2663,9 @@ int acornscsi_detect(Scsi_Host_Template * tpnt)
host->dma.io_port = instance->io_port + 0xc00;
host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800;
+ ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr);
+ ecs[count]->irqmask = 0x0a;
+
request_region (instance->io_port + 0x800, 2, "acornscsi(sbic)");
request_region (host->card.io_intr, 1, "acornscsi(intr)");
request_region (host->card.io_page, 1, "acornscsi(page)");
diff --git a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c
index 38b78f721..797eaae06 100644
--- a/drivers/acorn/scsi/cumana_2.c
+++ b/drivers/acorn/scsi/cumana_2.c
@@ -156,8 +156,6 @@ cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs)
static void
cumanascsi_2_invalidate(char *addr, long len, fasdmadir_t direction)
{
- unsigned int page;
-
if (direction == DMA_OUT)
dma_cache_wback((unsigned long)addr, (unsigned long)len);
else
diff --git a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c
index f58fad4a9..301b83d05 100644
--- a/drivers/acorn/scsi/eesox.c
+++ b/drivers/acorn/scsi/eesox.c
@@ -164,8 +164,6 @@ eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
static void
eesoxscsi_invalidate(char *addr, long len, fasdmadir_t direction)
{
- unsigned int page;
-
if (direction == DMA_OUT)
dma_cache_wback((unsigned long)addr, (unsigned long)len);
else
diff --git a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c
index b6ffe08d9..6cd638242 100644
--- a/drivers/acorn/scsi/fas216.c
+++ b/drivers/acorn/scsi/fas216.c
@@ -2049,7 +2049,7 @@ int fas216_init(struct Scsi_Host *instance)
save_flags(flags);
sti();
- while (jiffies < target_jiffies) barrier();
+ while (time_before(jiffies, target_jiffies)) barrier();
restore_flags(flags);
diff --git a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c
index db9ec0a8f..caae8a8ba 100644
--- a/drivers/acorn/scsi/powertec.c
+++ b/drivers/acorn/scsi/powertec.c
@@ -152,8 +152,6 @@ powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
static void
powertecscsi_invalidate(char *addr, long len, fasdmadir_t direction)
{
- unsigned int page;
-
if (direction == DMA_OUT)
dma_cache_wback((unsigned long)addr, (unsigned long)len);
else
diff --git a/drivers/ap1000/ddv_util.c b/drivers/ap1000/ddv_util.c
index b853a3216..d6cf12216 100644
--- a/drivers/ap1000/ddv_util.c
+++ b/drivers/ap1000/ddv_util.c
@@ -92,7 +92,7 @@ int ddv_restart_cpu(void)
return(-1);
}
for (timeout=jiffies + 10;
- (jiffies < timeout) || (OPT_IO(PBUF0) == 0);
+ time_before(jiffies, timeout) || (OPT_IO(PBUF0) == 0);
) /* wait */ ;
if (OPT_IO(PBUF0) == 0) {
printk("WARNING: option kernel didn't startup\n");
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index a4920df2a..de2ca9c88 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -69,7 +69,7 @@ else
bool ' QDI QD6580 support' CONFIG_BLK_DEV_QD6580
bool ' UMC-8672 support' CONFIG_BLK_DEV_UMC8672
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
+ if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" ]; then
bool ' PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
fi
fi
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 9d6c4fb00..b1433046f 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -425,7 +425,7 @@ int acsi_wait_for_IRQ( unsigned timeout )
{
if (INT_LEVEL < 6) {
unsigned long maxjif;
- for( maxjif = jiffies + timeout; jiffies < maxjif; )
+ for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); )
if (!(mfp.par_dt_reg & 0x20)) return( 1 );
}
else {
@@ -442,7 +442,7 @@ int acsi_wait_for_noIRQ( unsigned timeout )
{
if (INT_LEVEL < 6) {
unsigned long maxjif;
- for( maxjif = jiffies + timeout; jiffies < maxjif; )
+ for( maxjif = jiffies + timeout; time_before(jiffies, maxjif); )
if (mfp.par_dt_reg & 0x20) return( 1 );
}
else {
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 66121340f..1f5d31b88 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -101,17 +101,8 @@ not be guaranteed. There are several ways to assure this:
cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \
} while(0)
-#define START_TIMER(to) \
- do { \
- del_timer( &slm_timer ); \
- slm_timer.expires = jiffies + (to); \
- add_timer( &slm_timer ); \
- } while(0)
-
-#define STOP_TIMER() \
- do { \
- del_timer( &slm_timer ); \
- } while(0)
+#define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to))
+#define STOP_TIMER() del_timer(&slm_timer)
static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 };
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 5c55700a7..4f22bd609 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1838,7 +1838,7 @@ __initfunc(static int fd_test_drive_present( int drive ))
FDC_WRITE (FDCREG_TRACK, 0xff00);
FDC_WRITE( FDCREG_CMD, FDCCMD_RESTORE | FDCCMDADD_H | FDCSTEP_6 );
- for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; jiffies < timeout; ) {
+ for( ok = 0, timeout = jiffies + 2*HZ+HZ/2; time_before(jiffies, timeout); ) {
if (!(mfp.par_dt_reg & 0x20))
break;
}
diff --git a/drivers/block/cmd640.c b/drivers/block/cmd640.c
index 5ffbefaf0..998249370 100644
--- a/drivers/block/cmd640.c
+++ b/drivers/block/cmd640.c
@@ -5,10 +5,10 @@
*/
/*
- * Original author: abramov@cecmow.enet.dec.com (Igor Abramov)
+ * Original authors: abramov@cecmow.enet.dec.com (Igor Abramov)
+ * mlord@pobox.com (Mark Lord)
*
- * Maintained by: mlord@pobox.com (Mark Lord)
- * with fanatical support from a legion of hackers!
+ * See linux/MAINTAINERS for address of current maintainer.
*
* This file provides support for the advanced features and bugs
* of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 1a40d6009..4c18a79dd 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4156,6 +4156,7 @@ __initfunc(int floppy_init(void))
fdc_state[1].address = FDC2;
#endif
+ fdc = 0; /* reset fdc in case of unexpected interrupt */
if (floppy_grab_irq_and_dma()){
del_timer(&fd_timeout);
blk_dev[MAJOR_NR].request_fn = NULL;
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 7fb8430ee..889913b54 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -317,11 +317,50 @@ solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
#endif
#ifdef CONFIG_BSD_DISKLABEL
+static void check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p)
+{
+ struct hd_struct *lin_p;
+ /* check relative position of partitions. */
+ for (lin_p = hd->part + 1; lin_p - hd->part < current_minor; lin_p++) {
+ /* no relationship -> try again */
+ if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset
+ || lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
+ continue;
+ /* equal -> no need to add */
+ if (lin_p->start_sect == bsd_p->p_offset &&
+ lin_p->nr_sects == bsd_p->p_size)
+ return;
+ /* bsd living within dos partition */
+ if (lin_p->start_sect <= bsd_p->p_offset && lin_p->start_sect
+ + lin_p->nr_sects >= bsd_p->p_offset + bsd_p->p_size) {
+#ifdef DEBUG_BSD_DISKLABEL
+ printk("w: %d %ld+%ld,%d+%d",
+ lin_p - hd->part,
+ lin_p->start_sect, lin_p->nr_sects,
+ bsd_p->p_offset, bsd_p->p_size);
+#endif
+ break;
+ }
+ /* ouch: bsd and linux overlap. Don't even try for that partition */
+#ifdef DEBUG_BSD_DISKLABEL
+ printk("???: %d %ld+%ld,%d+%d",
+ lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
+ bsd_p->p_offset, bsd_p->p_size);
+#endif
+ printk("???");
+ return;
+ } /* if the bsd partition is not currently known to linux, we end
+ * up here
+ */
+ add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
+ current_minor++;
+}
/*
* Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See extended_partition() for more information.
*/
-static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
+static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev,
+ int max_partitions)
{
struct buffer_head *bh;
struct bsd_disklabel *l;
@@ -337,19 +376,56 @@ static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
return;
}
- p = &l->d_partitions[0];
- while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
+ if (l->d_npartitions < max_partitions)
+ max_partitions = l->d_npartitions;
+ for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
if ((current_minor & mask) >= (4 + hd->max_p))
break;
- if (p->p_fstype != BSD_FS_UNUSED) {
- add_partition(hd, current_minor, p->p_offset, p->p_size);
+ if (p->p_fstype != BSD_FS_UNUSED)
+ check_and_add_bsd_partition(hd, p);
+ }
+ brelse(bh);
+
+}
+#endif
+
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+/*
+ * Create devices for Unixware partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void unixware_partition(struct gendisk *hd, kdev_t dev)
+{
+ struct buffer_head *bh;
+ struct unixware_disklabel *l;
+ struct unixware_slice *p;
+ int mask = (1 << hd->minor_shift) - 1;
+
+ if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
+ return;
+ bh->b_state = 0;
+ l = (struct unixware_disklabel *) (bh->b_data+512);
+ if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
+ le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
+ brelse(bh);
+ return;
+ }
+ printk(" <unixware:");
+ p = &l->vtoc.v_slice[1];
+ /* I omit the 0th slice as it is the same as whole disk. */
+ while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
+ if ((current_minor & mask) == 0)
+ break;
+
+ if (p->s_label != UNIXWARE_FS_UNUSED) {
+ add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
current_minor++;
}
p++;
}
brelse(bh);
-
+ printk(" >");
}
#endif
@@ -360,6 +436,11 @@ static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_s
struct partition *p;
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
+#ifdef CONFIG_BSD_DISKLABEL
+ /* no bsd disklabel as a default */
+ kdev_t bsd_kdev = 0;
+ int bsd_maxpart = BSD_MAXPARTITIONS;
+#endif
#ifdef CONFIG_BLK_DEV_IDE
int tested_for_xlate = 0;
@@ -476,12 +557,23 @@ check_table:
hd->part[minor].nr_sects = 2;
}
#ifdef CONFIG_BSD_DISKLABEL
- if (SYS_IND(p) == BSD_PARTITION) {
- printk(" <");
- bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
- printk(" >");
+ /* tag first disklabel for late recognition */
+ if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
+ printk("!");
+ if (!bsd_kdev)
+ bsd_kdev = MKDEV(hd->major, minor);
+ } else if (SYS_IND(p) == OPENBSD_PARTITION) {
+ printk("!");
+ if (!bsd_kdev) {
+ bsd_kdev = MKDEV(hd->major, minor);
+ bsd_maxpart = OPENBSD_MAXPARTITIONS;
+ }
}
#endif
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+ if (SYS_IND(p) == UNIXWARE_PARTITION)
+ unixware_partition(hd, MKDEV(hd->major, minor));
+#endif
#ifdef CONFIG_SOLARIS_X86_PARTITION
/* james@bpgc.com: Solaris has a nasty indicator: 0x82
@@ -495,6 +587,13 @@ check_table:
}
#endif
}
+#ifdef CONFIG_BSD_DISKLABEL
+ if (bsd_kdev) {
+ printk(" <");
+ bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
+ printk(" >");
+ }
+#endif
/*
* Check for old-style Disk Manager partition table
*/
@@ -1235,7 +1334,7 @@ __initfunc(void device_setup(void))
int get_partition_list(char * page)
{
struct gendisk *p;
- char buf[8];
+ char buf[32];
int n, len;
len = sprintf(page, "major minor #blocks name\n\n");
diff --git a/drivers/block/hd.c b/drivers/block/hd.c
index bd92e85e6..5674e3070 100644
--- a/drivers/block/hd.c
+++ b/drivers/block/hd.c
@@ -783,6 +783,7 @@ static struct file_operations hd_fops = {
hd_ioctl, /* ioctl */
NULL, /* mmap */
hd_open, /* open */
+ NULL, /* flush */
hd_release, /* release */
block_fsync /* fsync */
};
diff --git a/drivers/block/ide-cd.c b/drivers/block/ide-cd.c
index 2231f5693..2e1f9ba76 100644
--- a/drivers/block/ide-cd.c
+++ b/drivers/block/ide-cd.c
@@ -1,9 +1,8 @@
-#define VERBOSE_IDE_CD_ERRORS 1
/*
* linux/drivers/block/ide-cd.c
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998 Jens Axboe and Chris Zwilling
+ * Copyright (C) 1998, 1999 Jens Axboe
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
@@ -18,7 +17,7 @@
* ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
*
* Drives that deviate from the ATAPI standard will be accomodated as much
- * as possable via compile time or command-line options. Since I only have
+ * as possible via compile time or command-line options. Since I only have
* a few drives, you generally need to send me patches...
*
* ----------------------------------
@@ -28,17 +27,12 @@
* This will allow us to get automagically notified when the media changes
* on ATAPI drives (something the stock ATAPI spec is lacking). Looks
* very cool. I discovered its existance the other day at work...
- * -Fix ide_cdrom_reset so that it works (it does nothing right now)
* -Query the drive to find what features are available before trying to
* use them (like trying to close the tray in drives that can't).
* -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
* boot
- * -Handle older drives that can't report their speed. (i.e. check if they
- * support a version of ATAPI where they can report their speed before
- * checking their speed and believing what they return).
- * -It seems we do not always honor it when Uniform gets a request to change
- * the cdi->options. We should _always_ check the options before doing stuff.
- * This must be fixed.
+ * -Integrate DVD-ROM support in driver. Thanks to Merete Gotsæd-Petersen
+ * of Pioneer Denmark for providing me with a drive for testing.
*
*
* ----------------------------------
@@ -226,9 +220,19 @@
* Jens Axboe <axboe@image.dk>
* Chris Zwilling <chris@cloudnet.com>
*
+ * 4.51 Dec 23, 1998 -- Jens Axboe <axboe@image.dk>
+ * - ide_cdrom_reset enabled since the ide subsystem
+ * handles resets fine now. <axboe@image.dk>
+ * - Transfer size fix for Samsung CD-ROMs, thanks to
+ * "Ville Hallik" <ville.hallik@mail.ee>.
+ * - other minor stuff.
+ *
+ * 4.52 Jan 19, 1999 -- Jens Axboe <axboe@image.dk>
+ * - Detect DVD-ROM/RAM drives
+ *
*************************************************************************/
-#define IDECD_VERSION "4.50"
+#define IDECD_VERSION "4.52"
#include <linux/module.h>
#include <linux/types.h>
@@ -456,7 +460,7 @@ static void cdrom_queue_request_sense (ide_drive_t *drive,
len *= 4;
pc->c[0] = REQUEST_SENSE;
- pc->c[4] = len;
+ pc->c[4] = (unsigned char) len;
pc->buffer = (char *)reqbuf;
pc->buflen = len;
pc->sense_data = (struct atapi_request_sense *)failed_command;
@@ -856,7 +860,12 @@ static void cdrom_read_intr (ide_drive_t *drive)
if ((len % SECTOR_SIZE) != 0) {
printk ("%s: cdrom_read_intr: Bad transfer size %d\n",
drive->name, len);
- printk (" This drive is not supported by this version of the driver\n");
+ if (CDROM_CONFIG_FLAGS (drive)->limit_nframes)
+ printk (" This drive is not supported by this version of the driver\n");
+ else {
+ printk (" Trying to limit transfer sizes\n");
+ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
+ }
cdrom_end_request (0, drive);
return;
}
@@ -992,7 +1001,6 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
{
struct packet_command pc;
struct request *rq = HWGROUP(drive)->rq;
-
int nsect, sector, nframes, frame, nskip;
/* Number of sectors to transfer. */
@@ -1029,8 +1037,10 @@ static void cdrom_start_read_continuation (ide_drive_t *drive)
nframes = (nsect + SECTORS_PER_FRAME-1) / SECTORS_PER_FRAME;
frame = sector / SECTORS_PER_FRAME;
- /* Largest number of frames was can transfer at once is 64k-1. */
- nframes = MIN (nframes, 65535);
+ /* Largest number of frames was can transfer at once is 64k-1. For
+ some drives we need to limit this even more. */
+ nframes = MIN (nframes, (CDROM_CONFIG_FLAGS (drive)->limit_nframes) ?
+ (65534 / CD_FRAMESIZE) : 65535);
/* Set up the command */
memset (&pc.c, 0, sizeof (pc.c));
@@ -1328,7 +1338,7 @@ int cdrom_queue_packet_command (ide_drive_t *drive, struct packet_command *pc)
struct atapi_request_sense *reqbuf = pc->sense_data;
if (reqbuf->sense_key == UNIT_ATTENTION)
- ;
+ cdrom_saw_media_change (drive);
else if (reqbuf->sense_key == NOT_READY &&
reqbuf->asc == 4) {
/* The drive is in the process of loading
@@ -2477,19 +2487,12 @@ static
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
-/* This doesn't work reliably yet, and so it is currently just a stub. */
-
-#if 0
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct request req;
+
ide_init_drive_cmd (&req);
req.cmd = RESET_DRIVE_COMMAND;
return ide_do_drive_cmd (drive, &req, ide_wait);
-#endif
-
-/* For now, just return 0, as if things had worked... */
- return 0;
-
}
@@ -2573,8 +2576,7 @@ int ide_cdrom_select_disc (struct cdrom_device_info *cdi, int slot)
curslot = CDROM_STATE_FLAGS (drive)->sanyo_slot;
if (curslot == 3)
curslot = 0;
- }
- else
+ } else
#endif /* not STANDARD_ATAPI */
{
stat = cdrom_read_changer_info (drive);
@@ -2655,10 +2657,10 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
return CDS_DISC_OK;
if (my_reqbuf.sense_key == NOT_READY) {
- /* With my NEC260, at least, we can't distinguish
- between tray open and tray closed but no disc
- inserted. */
- return CDS_TRAY_OPEN;
+ /* ATAPI doesn't have anything that can help
+ us decide whether the drive is really
+ emtpy or the tray is just open. irk. */
+ return CDS_TRAY_OPEN;
}
return CDS_DRIVE_NOT_READY;
@@ -2834,14 +2836,12 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
static
int ide_cdrom_probe_capabilities (ide_drive_t *drive)
{
- int stat, nslots, attempts = 3;
+ int stat, nslots = 0, attempts = 3;
struct {
char pad[8];
struct atapi_capabilities_page cap;
} buf;
- nslots = 0;
-
if (CDROM_CONFIG_FLAGS (drive)->nec260)
return nslots;
@@ -2860,6 +2860,14 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->cd_r = 1;
if (buf.cap.cd_rw_write)
CDROM_CONFIG_FLAGS (drive)->cd_rw = 1;
+ if (buf.cap.test_write)
+ CDROM_CONFIG_FLAGS (drive)->test_write = 1;
+ if (buf.cap.dvd_ram_read || buf.cap.dvd_r_read || buf.cap.dvd_rom)
+ CDROM_CONFIG_FLAGS (drive)->dvd = 1;
+ if (buf.cap.dvd_ram_write)
+ CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
+ if (buf.cap.dvd_r_write)
+ CDROM_CONFIG_FLAGS (drive)->dvd_rw = 1;
#if ! STANDARD_ATAPI
if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
@@ -2895,18 +2903,26 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
}
- printk ("%s: ATAPI %dX CDROM",
- drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed);
+ printk ("%s: ATAPI %dX %s",
+ drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed,
+ (CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM");
+
+ if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_rw)
+ printk (" DVD%s%s",
+ (CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-RAM" : "",
+ (CDROM_CONFIG_FLAGS (drive)->dvd_rw)? "/RW" : "");
+
if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw)
printk (" CD%s%s",
(CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "",
(CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
+
if (CDROM_CONFIG_FLAGS (drive)->is_changer)
printk (" changer w/%d slots", nslots);
else
printk (" drive");
- printk (", %dkB Cache\n",
- ntohs(buf.cap.buffer_size) );
+
+ printk (", %dkB Cache\n", ntohs(buf.cap.buffer_size));
return nslots;
}
@@ -2916,10 +2932,10 @@ static void ide_cdrom_add_settings(ide_drive_t *drive)
int major = HWIF(drive)->major;
int minor = drive->select.b.unit << PARTN_BITS;
- ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
- ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
- ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
- ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
+ ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
+ ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
+ ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
+ ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL);
}
static
@@ -2957,8 +2973,19 @@ int ide_cdrom_setup (ide_drive_t *drive)
CDROM_CONFIG_FLAGS (drive)->is_changer = 0;
CDROM_CONFIG_FLAGS (drive)->cd_r = 0;
CDROM_CONFIG_FLAGS (drive)->cd_rw = 0;
+ CDROM_CONFIG_FLAGS (drive)->test_write = 0;
+ CDROM_CONFIG_FLAGS (drive)->dvd = 0;
+ CDROM_CONFIG_FLAGS (drive)->dvd_r = 0;
+ CDROM_CONFIG_FLAGS (drive)->dvd_rw = 0;
CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
+
+ /* limit transfer size per interrupt. currently only one Samsung
+ drive needs this. */
+ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 0;
+ if (drive->id != NULL)
+ if (strcmp (drive->id->model, "SAMSUNG CD-ROM SCR-2432") == 0)
+ CDROM_CONFIG_FLAGS (drive)->limit_nframes = 1;
#if ! STANDARD_ATAPI
/* by default Sanyo 3 CD changer support is turned off and
diff --git a/drivers/block/ide-cd.h b/drivers/block/ide-cd.h
index e72777fdd..289b656ba 100644
--- a/drivers/block/ide-cd.h
+++ b/drivers/block/ide-cd.h
@@ -4,7 +4,7 @@
* linux/drivers/block/ide_modes.h
*
* Copyright (C) 1996 Erik Andersen
- * Copyright (C) 1998 Jens Axboe and Chris Zwilling
+ * Copyright (C) 1998, 1999 Jens Axboe
*/
#include <asm/byteorder.h>
@@ -14,7 +14,7 @@
memory, though. */
#ifndef VERBOSE_IDE_CD_ERRORS
-#define VERBOSE_IDE_CD_ERRORS 0
+#define VERBOSE_IDE_CD_ERRORS 1
#endif
@@ -128,8 +128,15 @@ struct ide_cd_config_flags {
__u8 is_changer : 1; /* Drive is a changer. */
__u8 cd_r : 1; /* Drive can write to CD-R media . */
__u8 cd_rw : 1; /* Drive can write to CD-R/W media . */
+ __u8 dvd : 1; /* Drive is a DVD-ROM */
+ __u8 dvd_r : 1; /* Drive can write DVD-RAM */
+ __u8 dvd_rw : 1; /* Drive can write DVD-R/W */
+ __u8 test_write : 1; /* Drive can fake writes */
__u8 supp_disc_present: 1; /* Changer can report exact contents
of slots. */
+ __u8 limit_nframes : 1; /* Drive does not provide data in
+ multiples of SECTOR_SIZE when more
+ than one interrupt is needed. */
__u8 seeking : 1; /* Seeking in progress */
__u8 reserved : 6;
byte max_speed; /* Max speed of the drive */
@@ -291,44 +298,69 @@ struct atapi_capabilities_page {
byte page_length;
#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved2 : 5;
+ __u8 reserved2 : 2;
+ /* Drive supports reading of DVD-RAM discs */
+ __u8 dvd_ram_read : 1;
+ /* Drive supports reading of DVD-R discs */
+ __u8 dvd_r_read : 1;
+ /* Drive supports reading of DVD-ROM discs */
+ __u8 dvd_rom : 1;
/* Drive supports reading CD-R discs with addressing method 2 */
__u8 method2 : 1; /* reserved in 1.2 */
/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
+ __u8 cd_rw_read : 1; /* reserved in 1.2 */
/* Drive supports read from CD-R discs (orange book, part II) */
__u8 cd_r_read : 1; /* reserved in 1.2 */
#elif defined(__LITTLE_ENDIAN_BITFIELD)
/* Drive supports read from CD-R discs (orange book, part II) */
- __u8 cd_r_read : 1; /* reserved in 1.2 */
+ __u8 cd_r_read : 1; /* reserved in 1.2 */
/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_read : 1; /* reserved in 1.2 */
+ __u8 cd_rw_read : 1; /* reserved in 1.2 */
/* Drive supports reading CD-R discs with addressing method 2 */
- __u8 method2 : 1; /* reserved in 1.2 */
- __u8 reserved2 : 5;
+ __u8 method2 : 1;
+ /* Drive supports reading of DVD-ROM discs */
+ __u8 dvd_rom : 1;
+ /* Drive supports reading of DVD-R discs */
+ __u8 dvd_r_read : 1;
+ /* Drive supports reading of DVD-RAM discs */
+ __u8 dvd_ram_read : 1;
+ __u8 reserved2 : 2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved3 : 6;
+ __u8 reserved3 : 2;
+ /* Drive can fake writes */
+ __u8 test_write : 1;
+ __u8 reserved3a : 1;
+ /* Drive can write DVD-R discs */
+ __u8 dvd_r_write : 1;
+ /* Drive can write DVD-RAM discs */
+ __u8 dvd_ram_write : 1;
/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
+ __u8 cd_rw_write : 1; /* reserved in 1.2 */
/* Drive supports write to CD-R discs (orange book, part II) */
__u8 cd_r_write : 1; /* reserved in 1.2 */
#elif defined(__LITTLE_ENDIAN_BITFIELD)
-
/* Drive can write to CD-R discs (orange book, part II) */
- __u8 cd_r_write : 1; /* reserved in 1.2 */
+ __u8 cd_r_write : 1; /* reserved in 1.2 */
/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
- __u8 cd_rw_write : 1; /* reserved in 1.2 */
- __u8 reserved3 : 6;
+ __u8 cd_rw_write : 1; /* reserved in 1.2 */
+ /* Drive can write DVD-RAM discs */
+ __u8 dvd_ram_write : 1;
+ /* Drive can write DVD-R discs */
+ __u8 dvd_r_write : 1;
+ __u8 reserved3a : 1;
+ /* Drive can fake writes */
+ __u8 test_write : 1;
+ __u8 reserved3 : 2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
#if defined(__BIG_ENDIAN_BITFIELD)
- __u8 reserved4 : 1;
+ __u8 reserved4 : 4;
/* Drive can read multisession discs. */
__u8 multisession : 1;
/* Drive can read mode 2, form 2 data. */
@@ -401,7 +433,7 @@ struct atapi_capabilities_page {
#if defined(__BIG_ENDIAN_BITFIELD)
/* Drive mechanism types. */
- mechtype_t mechtype : 3;
+ mechtype_t mechtype : 3;
__u8 reserved6 : 1;
/* Drive can eject a disc or changer cartridge. */
__u8 eject : 1;
@@ -423,7 +455,7 @@ struct atapi_capabilities_page {
__u8 eject : 1;
__u8 reserved6 : 1;
/* Drive mechanism types. */
- mechtype_t mechtype : 3;
+ mechtype_t mechtype : 3;
#else
#error "Please fix <asm/byteorder.h>"
#endif
@@ -742,7 +774,7 @@ const struct {
{ 0x6300, "End of user area encountered on this track" },
- { 0x6400, "Illegal mode for this track" },
+ { 0x6400, "Illegal mode for this track or incompatible medium" },
{ 0xb900, "Play operation oborted (sic)" },
diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c
index 2062f5cdf..f84ac8f14 100644
--- a/drivers/block/ide-disk.c
+++ b/drivers/block/ide-disk.c
@@ -1,12 +1,14 @@
/*
- * linux/drivers/block/ide-disk.c Version 1.04 Jan 7, 1998
+ * linux/drivers/block/ide-disk.c Version 1.08 Dec 10, 1998
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
/*
- * Maintained by Mark Lord <mlord@pobox.com>
- * and Gadi Oxman <gadio@netvision.net.il>
+ * Mostly written by Mark Lord <mlord@pobox.com>
+ * and Gadi Oxman <gadio@netvision.net.il>
+ *
+ * See linux/MAINTAINERS for address of current maintainer.
*
* This is the IDE/ATA disk driver, as evolved from hd.c and ide.c.
*
@@ -19,10 +21,13 @@
* Version 1.05 add capacity support for ATA3 >= 8GB
* Version 1.06 get boot-up messages to show full cyl count
* Version 1.07 disable door-locking if it fails
- * Version 1.07a fixed mult_count enables
+ * Version 1.08 fixed CHS/LBA translations for ATA4 > 8GB,
+ * process of adding new ATA4 compliance.
+ * fixed problems in allowing fdisk to see
+ * the entire disk.
*/
-#define IDEDISK_VERSION "1.07"
+#define IDEDISK_VERSION "1.08"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -87,15 +92,33 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
unsigned long chs_sects = id->cyls * id->heads * id->sectors;
unsigned long _10_percent = chs_sects / 10;
- /* very large drives (8GB+) may lie about the number of cylinders */
- if (id->cyls == 16383 && id->heads == 16 && id->sectors == 63 && lba_sects > chs_sects) {
+ /*
+ * very large drives (8GB+) may lie about the number of cylinders
+ * This is a split test for drives 8 Gig and Bigger only.
+ */
+ if ((id->lba_capacity >= 16514064) && (id->cyls == 0x3fff) &&
+ (id->heads == 16) && (id->sectors == 63)) {
id->cyls = lba_sects / (16 * 63); /* correct cyls */
return 1; /* lba_capacity is our only option */
}
+ /*
+ * This is a split test for drives less than 8 Gig only.
+ * Drives less than 8GB sometimes declare that they have 15 heads.
+ * This is an accounting trick (0-15) == (1-16), just an initial
+ * zero point difference.
+ */
+ if ((id->lba_capacity < 16514064) && (lba_sects > chs_sects) &&
+ ((id->heads == 15) || (id->heads == 16)) && (id->sectors == 63)) {
+ if (id->heads == 15)
+ id->cyls = lba_sects / (15 * 63); /* correct cyls */
+ if (id->heads == 16)
+ id->cyls = lba_sects / (16 * 63); /* correct cyls */
+ return 1; /* lba_capacity is our only option */
+ }
/* perform a rough sanity check on lba_sects: within 10% is "okay" */
- if ((lba_sects - chs_sects) < _10_percent)
+ if ((lba_sects - chs_sects) < _10_percent) {
return 1; /* lba_capacity is good */
-
+ }
/* some drives have the word order reversed */
lba_sects = (lba_sects << 16) | (lba_sects >> 16);
if ((lba_sects - chs_sects) < _10_percent) {
@@ -487,13 +510,13 @@ static void idedisk_pre_reset (ide_drive_t *drive)
drive->special.b.set_multmode = 1;
}
+#ifdef CONFIG_PROC_FS
+
static int smart_enable(ide_drive_t *drive)
{
return ide_wait_cmd(drive, WIN_SMART, 0, SMART_ENABLE, 0, NULL);
}
-#ifdef CONFIG_PROC_FS
-
static int get_smart_values(ide_drive_t *drive, byte *buf)
{
(void) smart_enable(drive);
@@ -603,7 +626,7 @@ static void idedisk_add_settings(ide_drive_t *drive)
int major = HWIF(drive)->major;
int minor = drive->select.b.unit << PARTN_BITS;
- ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_SHORT, 0, 1023, 1, 1, &drive->bios_cyl, NULL);
+ ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_SHORT, 0, 65535, 1, 1, &drive->bios_cyl, NULL);
ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL);
@@ -676,9 +699,8 @@ static void idedisk_setup (ide_drive_t *drive)
drive->sect = drive->bios_sect = id->sectors;
}
/* Handle logical geometry translation by the drive */
- if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
- && (id->cur_heads <= 16) && id->cur_sectors)
- {
+ if ((id->field_valid & 1) && id->cur_cyls &&
+ id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
/*
* Extract the physical drive geometry for our use.
* Note that we purposely do *not* update the bios info.
@@ -703,27 +725,49 @@ static void idedisk_setup (ide_drive_t *drive)
}
}
/* Use physical geometry if what we have still makes no sense */
- if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) {
- drive->cyl = id->cyls;
- drive->head = id->heads;
- drive->sect = id->sectors;
+ if ((!drive->head || drive->head > 16) &&
+ id->heads && id->heads <= 16) {
+ if ((id->lba_capacity > 16514064) || (id->cyls == 0x3fff)) {
+ id->cyls = ((int)(id->lba_capacity/(id->heads * id->sectors)));
+ }
+ drive->cyl = id->cur_cyls = id->cyls;
+ drive->head = id->cur_heads = id->heads;
+ drive->sect = id->cur_sectors = id->sectors;
}
/* calculate drive capacity, and select LBA if possible */
- (void) idedisk_capacity (drive);
+ capacity = idedisk_capacity (drive);
- /* Correct the number of cyls if the bios value is too small */
- if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) {
- if (drive->cyl > drive->bios_cyl)
- drive->bios_cyl = drive->cyl;
+ /*
+ * if possible, give fdisk access to more of the drive,
+ * by correcting bios_cyls:
+ */
+ if ((capacity >= (drive->bios_cyl * drive->bios_sect * drive->bios_head)) &&
+ (!drive->forced_geom) && drive->bios_sect && drive->bios_head) {
+ drive->bios_cyl = (capacity / drive->bios_sect) / drive->bios_head;
+#ifdef DEBUG
+ printk("Fixing Geometry :: CHS=%d/%d/%d to CHS=%d/%d/%d\n",
+ drive->id->cur_cyls,
+ drive->id->cur_heads,
+ drive->id->cur_sectors,
+ drive->bios_cyl,
+ drive->bios_head,
+ drive->bios_sect);
+#endif
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
}
+
#if 0 /* done instead for entire identify block in arch/ide.h stuff */
/* fix byte-ordering of buffer size field */
id->buf_size = le16_to_cpu(id->buf_size);
#endif
printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d",
- drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2,
- drive->bios_cyl, drive->bios_head, drive->bios_sect);
+ drive->name, id->model,
+ capacity/2048L, id->buf_size/2,
+ drive->bios_cyl, drive->bios_head, drive->bios_sect);
+
if (drive->using_dma) {
if ((id->field_valid & 4) &&
(id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
@@ -735,12 +779,34 @@ static void idedisk_setup (ide_drive_t *drive)
}
}
printk("\n");
+
+ if (drive->select.b.lba) {
+ if (*(int *)&id->cur_capacity0 < id->lba_capacity) {
+#ifdef DEBUG
+ printk(" CurSects=%d, LBASects=%d, ",
+ *(int *)&id->cur_capacity0, id->lba_capacity);
+#endif
+ *(int *)&id->cur_capacity0 = id->lba_capacity;
+#ifdef DEBUG
+ printk( "Fixed CurSects=%d\n", *(int *)&id->cur_capacity0);
+#endif
+ }
+ }
+
drive->mult_count = 0;
if (id->max_multsect) {
+#if 1 /* original, pre IDE-NFG, per request of AC */
+ drive->mult_req = INITIAL_MULT_COUNT;
+ if (drive->mult_req > id->max_multsect)
+ drive->mult_req = id->max_multsect;
+ if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
+ drive->special.b.set_multmode = 1;
+#else
id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
id->multsect_valid = id->multsect ? 1 : 0;
drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
+#endif
}
drive->no_io_32bit = id->dword_io ? 1 : 0;
}
diff --git a/drivers/block/ide-dma.c b/drivers/block/ide-dma.c
index 058d93b85..a3ac37238 100644
--- a/drivers/block/ide-dma.c
+++ b/drivers/block/ide-dma.c
@@ -68,8 +68,9 @@
* SIIG's UltraIDE Pro CN-2449
* TTI HPT343 Chipset "Modified SCSI Class" but reports as an
* unknown storage device.
- * NEW check_drive_lists(ide_drive_t *drive, int good_bad)
+ * NEW check_drive_lists(ide_drive_t *drive, int good_bad)
*/
+
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -91,17 +92,26 @@
*/
const char *good_dma_drives[] = {"Micropolis 2112A",
"CONNER CTMA 4000",
+ "CONNER CTT8000-A",
"ST34342A", /* for Sun Ultra */
- "WDC AC2340F", /* DMA mode1 */
- "WDC AC2340H", /* DMA mode1 */
NULL};
/*
* bad_dma_drives() lists the model names (from "hdparm -i")
* of drives which supposedly support (U)DMA but which are
* known to corrupt data with this interface under Linux.
+ *
+ * This is an empirical list. Its generated from bug reports. That means
+ * while it reflects actual problem distributions it doesn't answer whether
+ * the drive or the controller, or cabling, or software, or some combination
+ * thereof is the fault. If you don't happen to agree with the kernel's
+ * opinion of your drive - use hdparm to turn DMA on.
*/
-const char *bad_dma_drives[] = {"WDC AC22100H",
+const char *bad_dma_drives[] = {"WDC AC11000H",
+ "WDC AC22100H",
+ "WDC AC32500H",
+ "WDC AC33100H",
+ "WDC AC31600H",
NULL};
/*
@@ -243,7 +253,7 @@ int check_drive_lists (ide_drive_t *drive, int good_bad)
list = bad_dma_drives;
while (*list) {
if (!strcmp(*list++,id->model)) {
- printk("%s: (U)DMA capability is broken for %s\n",
+ printk("%s: Disabling (U)DMA for %s\n",
drive->name, id->model);
return 1;
}
@@ -331,8 +341,8 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
return 0;
case ide_dma_end: /* returns 1 on error, 0 otherwise */
drive->waiting_for_dma = 0;
- dma_stat = inb(dma_base+2);
- outb(inb(dma_base)&~1, dma_base); /* stop DMA */
+ outb(inb(dma_base)&~1, dma_base); /* stop DMA */
+ dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
return (dma_stat & 7) != 4; /* verify good DMA status */
case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
@@ -359,7 +369,11 @@ int ide_release_dma (ide_hwif_t *hwif)
return 1;
}
-__initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports))
+/*
+ * This can be called for a dynamically installed interface. Don't initfunc it
+ */
+
+void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
{
static unsigned long dmatable = 0;
static unsigned leftover = 0;
diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c
index e5d48249d..30c862f11 100644
--- a/drivers/block/ide-floppy.c
+++ b/drivers/block/ide-floppy.c
@@ -633,6 +633,9 @@ static void idefloppy_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
}
if (error)
floppy->failed_pc = NULL;
+ /* Why does this happen? */
+ if (!rq)
+ return;
if (!IDEFLOPPY_RQ_CMD (rq->cmd)) {
ide_end_request (uptodate, hwgroup);
return;
diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c
index 88b0dc631..df9c715e1 100644
--- a/drivers/block/ide-pci.c
+++ b/drivers/block/ide-pci.c
@@ -44,6 +44,7 @@
#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF})
#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
+#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A})
#define DEVID_UM8886BF ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF})
#define DEVID_HPT343 ((ide_pci_devid_t){PCI_VENDOR_ID_TTI, PCI_DEVICE_ID_TTI_HPT343})
@@ -137,6 +138,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
{DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
{DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
+ {DEVID_UM8886A, "UM8886A", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_UM8886BF,"UM8886BF", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_HPT343, "HPT343", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 16 },
{IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }};
@@ -148,22 +150,15 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
*/
__initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
{
- unsigned int addressbios = 0;
-
- pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addressbios);
-
switch(dev->device) {
case PCI_DEVICE_ID_ARTOP_ATP850UF:
case PCI_DEVICE_ID_PROMISE_20246:
- pci_write_config_byte(dev, PCI_ROM_ADDRESS, PCI_ROM_ADDRESS_ENABLE);
- printk("%s: ROM enabled ", name);
-
- if (!addressbios) {
- printk("but no address\n");
- } else {
- printk("at 0x%08x\n", addressbios);
+ if (dev->rom_address) {
+ pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+ printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
}
-
+
if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) {
unsigned char irq1 = 0, irq2 = 0;
@@ -386,6 +381,10 @@ check_if_enabled:
mate->serialized = 1;
}
}
+ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF))
+ hwif->irq = hwif->channel ? 15 : 14;
+
#ifdef CONFIG_BLK_DEV_IDEDMA
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513))
autodma = 0;
diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c
index bcaa40221..8e0c54dc1 100644
--- a/drivers/block/ide-probe.c
+++ b/drivers/block/ide-probe.c
@@ -5,8 +5,10 @@
*/
/*
- * Maintained by Mark Lord <mlord@pobox.com>
- * and Gadi Oxman <gadio@netvision.net.il>
+ * Mostly written by Mark Lord <mlord@pobox.com>
+ * and Gadi Oxman <gadio@netvision.net.il>
+ *
+ * See linux/MAINTAINERS for address of current maintainer.
*
* This is the IDE probe module, as evolved from hd.c and ide.c.
*
@@ -291,7 +293,7 @@ static int do_probe (ide_drive_t *drive, byte cmd)
delay_50ms();
OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
timeout = jiffies;
- while ((GET_STAT() & BUSY_STAT) && jiffies < timeout + WAIT_WORSTCASE)
+ while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))
delay_50ms();
rc = try_to_identify(drive, cmd);
}
@@ -587,7 +589,12 @@ static int init_irq (ide_hwif_t *hwif)
drive->next = hwgroup->drive->next;
hwgroup->drive->next = drive;
}
- hwgroup->hwif = HWIF(hwgroup->drive);
+ if (!hwgroup->hwif) {
+ hwgroup->hwif = HWIF(hwgroup->drive);
+#ifdef DEBUG
+ printk("%s : Adding missed hwif to hwgroup!!\n", hwif->name);
+#endif
+ }
restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */
#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c
index f99fe7d41..5b618d8f2 100644
--- a/drivers/block/ide-tape.c
+++ b/drivers/block/ide-tape.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-tape.c Version 1.13 Jan 2, 1998
+ * linux/drivers/block/ide-tape.c Version 1.14 Dec 30, 1998
*
* Copyright (C) 1995 - 1998 Gadi Oxman <gadio@netvision.net.il>
*
@@ -212,6 +212,8 @@
* number of tape blocks.
* Add support for INTERRUPT DRQ devices.
* Ver 1.13 Jan 2 98 Add "speed == 0" work-around for HP COLORADO 5GB
+ * Ver 1.14 Dec 30 98 Partial fixes for the Sony/AIWA tape drives.
+ * Replace cli()/sti() with hwgroup spinlocks.
*
* Here are some words from the first releases of hd.c, which are quoted
* in ide.c and apply here as well:
@@ -479,6 +481,11 @@
#define IDETAPE_FIFO_THRESHOLD 2
/*
+ * Some tape drives require a long irq timeout
+ */
+#define IDETAPE_WAIT_CMD (60*HZ)
+
+/*
* DSC timings.
*/
#define IDETAPE_DSC_RW_MIN 5*HZ/100 /* 50 msec */
@@ -1432,8 +1439,7 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "Reached idetape_add_stage_tail\n");
#endif /* IDETAPE_DEBUG_LOG */
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
stage->next=NULL;
if (tape->last_stage != NULL)
tape->last_stage->next=stage;
@@ -1444,7 +1450,7 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
tape->next_stage=tape->last_stage;
tape->nr_stages++;
tape->nr_pending_stages++;
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
}
/*
@@ -1756,6 +1762,8 @@ static void idetape_pc_intr (ide_drive_t *drive)
ide__sti(); /* local CPU only */
+ if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
+ status.b.check = 0;
if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
#if IDETAPE_DEBUG_LOG
printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name);
@@ -1811,7 +1819,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
if (temp > pc->buffer_size) {
printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
idetape_discard_data (drive,bcount.all);
- ide_set_handler (drive,&idetape_pc_intr,WAIT_CMD);
+ ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD);
return;
}
#if IDETAPE_DEBUG_LOG
@@ -1833,7 +1841,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
pc->actually_transferred+=bcount.all; /* Update the current position */
pc->current_position+=bcount.all;
- ide_set_handler (drive,&idetape_pc_intr,WAIT_CMD); /* And set the interrupt handler again */
+ ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD); /* And set the interrupt handler again */
}
/*
@@ -1884,18 +1892,29 @@ static void idetape_transfer_pc(ide_drive_t *drive)
idetape_tape_t *tape = drive->driver_data;
idetape_pc_t *pc = tape->pc;
idetape_ireason_reg_t ireason;
+ int retries = 100;
if (ide_wait_stat (drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return;
}
ireason.all=IN_BYTE (IDE_IREASON_REG);
+ while (retries-- && (!ireason.b.cod || ireason.b.io)) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, retrying\n");
+ udelay(100);
+ ireason.all = IN_BYTE(IDE_IREASON_REG);
+ if (retries == 0) {
+ printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing a packet command, ignoring\n");
+ ireason.b.cod = 1;
+ ireason.b.io = 0;
+ }
+ }
if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n");
ide_do_reset (drive);
return;
}
- ide_set_handler(drive, &idetape_pc_intr, WAIT_CMD); /* Set the interrupt routine */
+ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD); /* Set the interrupt routine */
atapi_output_bytes (drive,pc->c,12); /* Send the actual packet */
}
@@ -1961,7 +1980,7 @@ static void idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
}
#endif /* CONFIG_BLK_DEV_IDEDMA */
if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
- ide_set_handler(drive, &idetape_transfer_pc, WAIT_CMD);
+ ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD);
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
} else {
OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
@@ -2313,7 +2332,7 @@ static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc)
* The caller should ensure that the request will not be serviced
* before we install the semaphore (usually by disabling interrupts).
*/
-static void idetape_wait_for_request (struct request *rq)
+static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
{
struct semaphore sem = MUTEX_LOCKED;
@@ -2324,7 +2343,9 @@ static void idetape_wait_for_request (struct request *rq)
}
#endif /* IDETAPE_DEBUG_BUGS */
rq->sem = &sem;
- down (&sem);
+ spin_unlock(&HWGROUP(drive)->spinlock);
+ down(&sem);
+ spin_lock_irq(&HWGROUP(drive)->spinlock);
}
/*
@@ -2398,11 +2419,10 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
*/
return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh));
}
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (tape->active_stage == tape->first_stage)
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
rq_ptr = &tape->first_stage->rq;
bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
@@ -2451,13 +2471,12 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
* Pay special attention to possible race conditions.
*/
while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (idetape_pipeline_active (tape)) {
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
} else {
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
idetape_insert_pipeline_into_queue (drive);
if (idetape_pipeline_active (tape))
continue;
@@ -2513,13 +2532,12 @@ static void idetape_discard_read_pipeline (ide_drive_t *drive)
if (tape->first_stage == NULL)
return;
-
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
tape->next_stage = NULL;
if (idetape_pipeline_active (tape))
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
while (tape->first_stage != NULL)
idetape_remove_stage_head (drive);
@@ -2539,8 +2557,7 @@ static void idetape_wait_for_pipeline (ide_drive_t *drive)
if (!idetape_pipeline_active (tape))
idetape_insert_pipeline_into_queue (drive);
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (!idetape_pipeline_active (tape))
goto abort;
#if IDETAPE_DEBUG_BUGS
@@ -2548,9 +2565,9 @@ static void idetape_wait_for_pipeline (ide_drive_t *drive)
printk ("ide-tape: tape->last_stage == NULL\n");
else
#endif /* IDETAPE_DEBUG_BUGS */
- idetape_wait_for_request (&tape->last_stage->rq);
+ idetape_wait_for_request(drive, &tape->last_stage->rq);
abort:
- restore_flags (flags); /* all CPUs (overkill?) */
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
}
static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
@@ -2795,11 +2812,10 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
* Wait until the first read-ahead request
* is serviced.
*/
- save_flags (flags); /* all CPUs (overkill?) */
- cli(); /* all CPUs (overkill?) */
+ spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
if (tape->active_stage == tape->first_stage)
- idetape_wait_for_request (tape->active_data_request);
- restore_flags (flags); /* all CPUs (overkill?) */
+ idetape_wait_for_request(drive, tape->active_data_request);
+ spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
count++;
@@ -3457,7 +3473,7 @@ static void idetape_get_mode_sense_results (ide_drive_t *drive)
return;
}
header = (idetape_mode_parameter_header_t *) pc.buffer;
- capabilities = (idetape_capabilities_page_t *) (header + 1);
+ capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
capabilities->max_speed = ntohs (capabilities->max_speed);
capabilities->ctl = ntohs (capabilities->ctl);
diff --git a/drivers/block/ide.c b/drivers/block/ide.c
index 23a554398..456ca470f 100644
--- a/drivers/block/ide.c
+++ b/drivers/block/ide.c
@@ -5,8 +5,10 @@
*/
/*
- * Maintained by Mark Lord <mlord@pobox.com>
- * and Gadi Oxman <gadio@netvision.net.il>
+ * Mostly written by Mark Lord <mlord@pobox.com>
+ * and Gadi Oxman <gadio@netvision.net.il>
+ *
+ * See linux/MAINTAINERS for address of current maintainer.
*
* This is the multiple IDE interface driver, as evolved from hd.c.
* It supports up to MAX_HWIFS IDE interfaces, on one or more IRQs (usually 14 & 15).
@@ -2130,6 +2132,12 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return -EIO;
return 0;
}
+ case HDIO_UNREGISTER_HWIF:
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ /* should I check here for arg > MAX_HWIFS, or
+ just let ide_unregister fail silently? -- shaver */
+ ide_unregister(arg);
+ return 0;
case HDIO_SET_NICE:
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (drive->driver == NULL)
@@ -2275,6 +2283,12 @@ __initfunc(static int match_parm (char *s, const char *keywords[], int vals[], i
* and quite likely to cause trouble with
* older/odd IDE drives.
*
+ * "hdx=slow" : insert a huge pause after each access to the data
+ * port. Should be used only as a last resort.
+ *
+ * "hdx=swapdata" : when the drive is a disk, byte swap all data
+ * "hdx=bswap" : same as above..........
+ *
* "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz,
* where "xx" is between 20 and 66 inclusive,
* used when tuning chipset PIO modes.
@@ -2333,12 +2347,16 @@ __initfunc(void ide_setup (char *s))
if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
"serialize", "autotune", "noautotune",
- "slow", "swapdata", NULL};
+ "slow", "swapdata", "bswap", NULL};
unit = s[2] - 'a';
hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES;
hwif = &ide_hwifs[hw];
drive = &hwif->drives[unit];
+ if (strncmp(s + 4, "ide-", 4) == 0) {
+ strncpy(drive->driver_req, s + 4, 9);
+ goto done;
+ }
switch (match_parm(&s[3], hd_words, vals, 3)) {
case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */
@@ -2366,7 +2384,8 @@ __initfunc(void ide_setup (char *s))
case -8: /* "slow" */
drive->slow = 1;
goto done;
- case -9: /* swapdata */
+ case -9: /* swapdata or bswap */
+ case -10:
drive->bswap = 1;
goto done;
case 3: /* cyl,head,sect */
@@ -2567,16 +2586,41 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
const byte *heads = head_vals;
unsigned long tracks;
- if ((drive = get_info_ptr(i_rdev)) == NULL || drive->forced_geom)
+ drive = get_info_ptr(i_rdev);
+ if (!drive)
return 0;
- if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63)
+ if (drive->forced_geom) {
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
+ return 0;
+ }
+
+ if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) {
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
return 0; /* we already have a translation */
+ }
printk("%s ", msg);
- if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63))
+ if (xparm < 0 && (drive->bios_cyl * drive->bios_head * drive->bios_sect) < (1024 * 16 * 63)) {
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
return 0; /* small disk: no translation needed */
+ }
if (drive->id) {
drive->cyl = drive->id->cyls;
@@ -2614,6 +2658,12 @@ int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
}
drive->part[0].nr_sects = current_capacity(drive);
printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
+ /*
+ * Update the current 3D drive values.
+ */
+ drive->id->cur_cyls = drive->bios_cyl;
+ drive->id->cur_heads = drive->bios_head;
+ drive->id->cur_sectors = drive->bios_sect;
return 1;
}
@@ -2703,7 +2753,11 @@ __initfunc(void ide_init_builtin_drivers (void))
(void) idefloppy_init();
#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
#ifdef CONFIG_BLK_DEV_IDESCSI
+ #ifdef CONFIG_SCSI
(void) idescsi_init();
+ #else
+ #warning ide scsi-emulation selected but no SCSI-subsystem in kernel
+ #endif
#endif /* CONFIG_BLK_DEV_IDESCSI */
}
diff --git a/drivers/block/ide.h b/drivers/block/ide.h
index 0919ca710..7c0b2555b 100644
--- a/drivers/block/ide.h
+++ b/drivers/block/ide.h
@@ -442,6 +442,8 @@ read_proc_t proc_ide_read_geometry;
*start = page + off; \
return len; \
}
+#else
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
#endif
/*
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 35403ce59..599268d26 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -644,91 +644,12 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
if (bh[i]) {
clear_bit(BH_Dirty, &bh[i]->b_state);
clear_bit(BH_Uptodate, &bh[i]->b_state);
+ bh[i]->b_end_io(bh[i], 0);
}
}
return;
}
-void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf)
-{
- int i, j;
- int buffersize;
- int max_req;
- unsigned long rsector;
- kdev_t rdev;
- struct request * req[8];
- unsigned int major = MAJOR(dev);
- struct semaphore sem = MUTEX_LOCKED;
-
- if (major >= MAX_BLKDEV || !(blk_dev[major].request_fn)) {
- printk(KERN_NOTICE "ll_rw_swap_file: trying to swap to"
- " nonexistent block-device\n");
- return;
- }
- max_req = NR_REQUEST;
- switch (rw) {
- case READ:
- break;
- case WRITE:
- max_req = (NR_REQUEST * 2) / 3;
- if (is_read_only(dev)) {
- printk(KERN_NOTICE
- "Can't swap to read-only device %s\n",
- kdevname(dev));
- return;
- }
- break;
- default:
- panic("ll_rw_swap: bad block dev cmd, must be R/W");
- }
- buffersize = PAGE_SIZE / nb;
-
- if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
- max_req >>= 1;
- for (j=0, i=0; i<nb;)
- {
- for (; j < 8 && i < nb; j++, i++, buf += buffersize)
- {
- rdev = dev;
- rsector = b[i] * (buffersize >> 9);
-#ifdef CONFIG_BLK_DEV_MD
- if (major==MD_MAJOR &&
- md_map (MINOR(dev), &rdev,
- &rsector, buffersize >> 9)) {
- printk (KERN_ERR
- "Bad md_map in ll_rw_swap_file\n");
- return;
- }
-#endif
-
- if (j == 0) {
- req[j] = get_request_wait(max_req, rdev);
- } else {
- unsigned long flags;
- spin_lock_irqsave(&io_request_lock,flags);
- req[j] = get_request(max_req, rdev);
- spin_unlock_irqrestore(&io_request_lock,flags);
- if (req[j] == NULL)
- break;
- }
- req[j]->cmd = rw;
- req[j]->errors = 0;
- req[j]->sector = rsector;
- req[j]->nr_sectors = buffersize >> 9;
- req[j]->current_nr_sectors = buffersize >> 9;
- req[j]->buffer = buf;
- req[j]->sem = &sem;
- req[j]->bh = NULL;
- req[j]->next = NULL;
- add_request(MAJOR(rdev)+blk_dev,req[j]);
- }
- run_task_queue(&tq_disk);
- while (j > 0) {
- j--;
- down(&sem);
- }
- }
-}
#ifdef CONFIG_STRAM_SWAP
extern int stram_device_init( void );
#endif
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f635dd6c0..56cf5fb13 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -225,6 +225,7 @@ repeat:
if (!create_missing_block(lo, block, blksize)) {
goto error_out_lock;
}
+ real_block = bmap(lo->lo_dentry->d_inode, block);
}
}
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 87a7d6495..8b316d116 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -44,8 +44,9 @@
#define LO_MAGIC 0x68797548
-static int nbd_blksizes[MAX_NBD] = {1024, 1024,};
-static int nbd_sizes[MAX_NBD] = {0x7fffffff, 0x7fffffff,};
+static int nbd_blksizes[MAX_NBD];
+static int nbd_sizes[MAX_NBD];
+static int nbd_bytesizes[MAX_NBD];
static struct nbd_device nbd_dev[MAX_NBD];
@@ -382,9 +383,11 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
if ((arg & 511) || (arg > PAGE_SIZE))
return -EINVAL;
nbd_blksizes[dev] = arg;
+ nbd_sizes[dev] = arg/nbd_blksizes[dev];
return 0;
case NBD_SET_SIZE:
- nbd_sizes[dev] = arg;
+ nbd_bytesizes[dev] = arg;
+ nbd_sizes[dev] = arg/nbd_blksizes[dev];
return 0;
case NBD_DO_IT:
if (!lo->file)
@@ -400,6 +403,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
dev, (long) lo->head, (long) lo->tail, requests_in, requests_out);
return 0;
#endif
+ case BLKGETSIZE:
+ return put_user(nbd_bytesizes[dev]/512, (long *) arg);
}
return -EINVAL;
}
@@ -472,6 +477,9 @@ int nbd_init(void)
nbd_dev[i].file = NULL;
nbd_dev[i].magic = LO_MAGIC;
nbd_dev[i].flags = 0;
+ nbd_blksizes[i] = 1024;
+ nbd_bytesizes[i] = 0x7fffffff;
+ nbd_sizes[i] = nbd_bytesizes[i]/nbd_blksizes[i];
}
return 0;
}
diff --git a/drivers/block/opti621.c b/drivers/block/opti621.c
index 41b87fbbe..bc2cf8949 100644
--- a/drivers/block/opti621.c
+++ b/drivers/block/opti621.c
@@ -1,20 +1,26 @@
/*
- * linux/drivers/block/opti621.c Version 0.3 Nov 29, 1997
+ * linux/drivers/block/opti621.c Version 0.6 Jan 02, 1999
*
- * Copyright (C) 1996-1998 Linus Torvalds & author (see below)
+ * Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
*/
/*
- * OPTi 82C621 chipset EIDE controller driver
- * Author: Jaromir Koutek (E-mail: Jaromir.Koutek@st.mff.cuni.cz)
- *
+ * Authors:
+ * Jaromir Koutek <miri@punknet.cz>,
+ * Jan Harkes <jaharkes@cwi.nl>,
+ * Mark Lord <mlord@pobox.com>
* Some parts of code are from ali14xx.c and from rz1000.c.
+ *
+ * OPTi is trademark of OPTi, Octek is trademark of Octek.
+ *
* I used docs from OPTi databook, from ftp.opti.com, file 9123-0002.ps
* and disassembled/traced setupvic.exe (DOS program).
* It increases kernel code about 2 kB.
+ * I don't have this card no more, but I hope I can get some in case
+ * of needed development.
* My card is Octek PIDE 1.01 (on card) or OPTiViC (program).
* It has a place for a secondary connector in circuit, but nothing
- * is there. It cost about $25. Also BIOS says no address for
+ * is there. Also BIOS says no address for
* secondary controller (see bellow in ide_init_opti621).
* I've only tested this on my system, which only has one disk.
* It's Western Digital WDAC2850, with PIO mode 3. The PCI bus
@@ -26,8 +32,18 @@
* with the third, 1GB drive: I got 3MB/s (hdparm), but sometimes
* it slows to about 100kB/s! I don't know why and I have
* not this drive now, so I can't try it again.
- * If you have two disk, please boot in single mode and carefully
- * (you can boot on read-only fs) try to set PIO mode 0 etc.
+ * I write this driver because I lost the paper ("manual") with
+ * settings of jumpers on the card and I have to boot Linux with
+ * Loadlin except LILO, cause I have to run the setupvic.exe program
+ * already or I get disk errors (my test: rpm -Vf
+ * /usr/X11R6/bin/XF86_SVGA - or any big file).
+ * Some numbers from hdparm -t /dev/hda:
+ * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec
+ * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec
+ * I have 4 Megs/s before, but I don't know why (maybe changes
+ * in hdparm test).
+ * After release of 0.1, I got some successful reports, so it might work.
+ *
* The main problem with OPTi is that some timings for master
* and slave must be the same. For example, if you have master
* PIO 3 and slave PIO 0, driver have to set some timings of
@@ -38,25 +54,37 @@
* for autoselect mode (you can change it to PIO 0, if you want).
* If you then set the second drive to another PIO, the old value
* (automatically selected) will be overrided by yours.
- * I don't know what there is a 25/33MHz switch in configuration
- * register, driver is written for use at any frequency which get
+ * There is a 25/33MHz switch in configuration
+ * register, but driver is written for use at any frequency which get
* (use idebus=xx to select PCI bus speed).
* Use ide0=autotune for automatical tune of the PIO modes.
* If you get strange results, do not use this and set PIO manually
* by hdparm.
- * I write this driver because I lost the paper ("manual") with
- * settings of jumpers on the card and I have to boot Linux with
- * Loadlin except LILO, cause I have to run the setupvic.exe program
- * already or I get disk errors (my test: rpm -Vf
- * /usr/X11R6/bin/XF86_SVGA - or any big file).
- * Some numbers from hdparm -t /dev/hda:
- * Timing buffer-cache reads: 32 MB in 3.02 seconds =10.60 MB/sec
- * Timing buffered disk reads: 16 MB in 5.52 seconds = 2.90 MB/sec
- * I have 4 Megs/s before, but I don't know why (maybe bad hdparm).
- * If you tried this driver, please send me a E-mail of your experiences.
- * My E-mail address is Jaromir.Koutek@st.mff.cuni.cz (I hope
- * till 30. 6. 2000), otherwise you can try miri@atrey.karlin.mff.cuni.cz.
- * I think OPTi is trademark of OPTi, Octek is trademark of Octek and so on.
+ *
+ * Version 0.1, Nov 8, 1996
+ * by Jaromir Koutek, for 2.1.8.
+ * Initial version of driver.
+ *
+ * Version 0.2
+ * Number 0.2 skipped.
+ *
+ * Version 0.3, Nov 29, 1997
+ * by Mark Lord (probably), for 2.1.68
+ * Updates for use with new IDE block driver.
+ *
+ * Version 0.4, Dec 14, 1997
+ * by Jan Harkes
+ * Fixed some errors and cleaned the code.
+ *
+ * Version 0.5, Jan 2, 1998
+ * by Jaromir Koutek
+ * Updates for use with (again) new IDE block driver.
+ * Update of documentation.
+ *
+ * Version 0.6, Jan 2, 1999
+ * by Jaromir Koutek
+ * Reversed to version 0.3 of the driver, because
+ * 0.5 doesn't work.
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -98,8 +126,10 @@
#define READ_REG 0 /* index of Read cycle timing register */
#define WRITE_REG 1 /* index of Write cycle timing register */
-#define MISC_REG 6 /* index of Miscellaneous register */
#define CNTRL_REG 3 /* index of Control register */
+#define STRAP_REG 5 /* index of Strap register */
+#define MISC_REG 6 /* index of Miscellaneous register */
+
int reg_base;
#define PIO_NOT_EXIST 254
@@ -203,9 +233,10 @@ static void compute_clocks(int pio, pio_clocks_t *clks)
clks->recovery_time = 2;
/* minimal values */
}
+
}
-/* Main tune procedure, hooked by tuneproc. */
+/* Main tune procedure, called from tuneproc. */
static void opti621_tune_drive (ide_drive_t *drive, byte pio)
{
/* primary and secondary drives share some registers,
@@ -218,7 +249,7 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio)
byte cycle1, cycle2, misc;
ide_hwif_t *hwif = HWIF(drive);
- /* set drive->drive_data for both drives */
+ /* sets drive->drive_data for both drives */
compute_pios(drive, pio);
pio1 = hwif->drives[0].drive_data;
pio2 = hwif->drives[1].drive_data;
@@ -250,7 +281,7 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio)
outb(0xff, reg_base+5); /* hmm, setupvic.exe does this ;-) */
inb(reg_base+CNTRL_REG); /* if reads 0xff, adapter not exist? */
read_reg(CNTRL_REG); /* if reads 0xc0, no interface exist? */
- read_reg(5); /* read version, probably 0 */
+ read_reg(STRAP_REG); /* read version, probably 0 */
/* program primary drive */
write_reg(0, MISC_REG); /* select Index-0 for Register-A */
diff --git a/drivers/block/paride/Config.in b/drivers/block/paride/Config.in
index 00dd9c8e4..8d4dc1742 100644
--- a/drivers/block/paride/Config.in
+++ b/drivers/block/paride/Config.in
@@ -16,6 +16,7 @@ dep_tristate ' FIT TD-2000 protocol' CONFIG_PARIDE_FIT2 $CONFIG_PARIDE
dep_tristate ' FIT TD-3000 protocol' CONFIG_PARIDE_FIT3 $CONFIG_PARIDE
dep_tristate ' Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE
dep_tristate ' Shuttle EPIA protocol' CONFIG_PARIDE_EPIA $CONFIG_PARIDE
+dep_tristate ' Freecom IQ ASIC-2 protocol' CONFIG_PARIDE_FRIQ $CONFIG_PARIDE
dep_tristate ' FreeCom power protocol' CONFIG_PARIDE_FRPW $CONFIG_PARIDE
dep_tristate ' KingByte KBIC-951A/971A protocols' CONFIG_PARIDE_KBIC $CONFIG_PARIDE
dep_tristate ' KT PHd protocol' CONFIG_PARIDE_KTTI $CONFIG_PARIDE
diff --git a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile
index ae2d54dd9..32e856704 100644
--- a/drivers/block/paride/Makefile
+++ b/drivers/block/paride/Makefile
@@ -147,6 +147,15 @@ else
endif
endif
+
+ifeq ($(CONFIG_PARIDE_FRIQ),y)
+ LX_OBJS += friq.o
+else
+ ifeq ($(CONFIG_PARIDE_FRIQ),m)
+ M_OBJS += friq.o
+ endif
+endif
+
ifeq ($(CONFIG_PARIDE_ON20),y)
LX_OBJS += on20.o
else
diff --git a/drivers/block/paride/friq.c b/drivers/block/paride/friq.c
new file mode 100644
index 000000000..37ebaa047
--- /dev/null
+++ b/drivers/block/paride/friq.c
@@ -0,0 +1,282 @@
+/*
+ friq.c (c) 1998 Grant R. Guenther <grant@torque.net>
+ Under the terms of the GNU public license
+
+ friq.c is a low-level protocol driver for the Freecom "IQ"
+ parallel port IDE adapter. Early versions of this adapter
+ use the 'frpw' protocol.
+
+ Freecom uses this adapter in a battery powered external
+ CD-ROM drive. It is also used in LS-120 drives by
+ Maxell and Panasonic, and other devices.
+
+ The battery powered drive requires software support to
+ control the power to the drive. This module enables the
+ drive power when the high level driver (pcd) is loaded
+ and disables it when the module is unloaded. Note, if
+ the friq module is built in to the kernel, the power
+ will never be switched off, so other means should be
+ used to conserve battery power.
+
+*/
+
+/* Changes:
+
+ 1.01 GRG 1998.12.20 Added support for soft power switch
+*/
+
+#define FRIQ_VERSION "1.01"
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "paride.h"
+
+#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\
+ w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x);
+
+#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
+
+/* cont = 0 - access the IDE register file
+ cont = 1 - access the IDE command set
+*/
+
+static int cont_map[2] = { 0x08, 0x10 };
+
+static int friq_read_regr( PIA *pi, int cont, int regr )
+
+{ int h,l,r;
+
+ r = regr + cont_map[cont];
+
+ CMD(r);
+ w2(6); l = r1();
+ w2(4); h = r1();
+ w2(4);
+
+ return j44(l,h);
+
+}
+
+static void friq_write_regr( PIA *pi, int cont, int regr, int val)
+
+{ int r;
+
+ r = regr + cont_map[cont];
+
+ CMD(r);
+ w0(val);
+ w2(5);w2(7);w2(5);w2(4);
+}
+
+static void friq_read_block_int( PIA *pi, char * buf, int count, int regr )
+
+{ int h, l, k, ph;
+
+ switch(pi->mode) {
+
+ case 0: CMD(regr);
+ for (k=0;k<count;k++) {
+ w2(6); l = r1();
+ w2(4); h = r1();
+ buf[k] = j44(l,h);
+ }
+ w2(4);
+ break;
+
+ case 1: ph = 2;
+ CMD(regr+0xc0);
+ w0(0xff);
+ for (k=0;k<count;k++) {
+ w2(0xa4 + ph);
+ buf[k] = r0();
+ ph = 2 - ph;
+ }
+ w2(0xac); w2(0xa4); w2(4);
+ break;
+
+ case 2: CMD(regr+0x80);
+ for (k=0;k<count-2;k++) buf[k] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ case 3: CMD(regr+0x80);
+ for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ case 4: CMD(regr+0x80);
+ for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
+ buf[count-4] = r4();
+ buf[count-3] = r4();
+ w2(0xac); w2(0xa4);
+ buf[count-2] = r4();
+ buf[count-1] = r4();
+ w2(4);
+ break;
+
+ }
+}
+
+static void friq_read_block( PIA *pi, char * buf, int count)
+
+{ friq_read_block_int(pi,buf,count,0x08);
+}
+
+static void friq_write_block( PIA *pi, char * buf, int count )
+
+{ int k;
+
+ switch(pi->mode) {
+
+ case 0:
+ case 1: CMD(8); w2(5);
+ for (k=0;k<count;k++) {
+ w0(buf[k]);
+ w2(7);w2(5);
+ }
+ w2(4);
+ break;
+
+ case 2: CMD(0xc8); w2(5);
+ for (k=0;k<count;k++) w4(buf[k]);
+ w2(4);
+ break;
+
+ case 3: CMD(0xc8); w2(5);
+ for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
+ w2(4);
+ break;
+
+ case 4: CMD(0xc8); w2(5);
+ for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
+ w2(4);
+ break;
+ }
+}
+
+static void friq_connect ( PIA *pi )
+
+{ pi->saved_r0 = r0();
+ pi->saved_r2 = r2();
+ w2(4);
+}
+
+static void friq_disconnect ( PIA *pi )
+
+{ CMD(0x20);
+ w0(pi->saved_r0);
+ w2(pi->saved_r2);
+}
+
+static int friq_test_proto( PIA *pi, char * scratch, int verbose )
+
+{ int j, k, r;
+ int e[2] = {0,0};
+
+ pi->saved_r0 = r0();
+ w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
+ udelay(500);
+ w0(pi->saved_r0);
+
+ friq_connect(pi);
+ for (j=0;j<2;j++) {
+ friq_write_regr(pi,0,6,0xa0+j*0x10);
+ for (k=0;k<256;k++) {
+ friq_write_regr(pi,0,2,k^0xaa);
+ friq_write_regr(pi,0,3,k^0x55);
+ if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
+ }
+ }
+ friq_disconnect(pi);
+
+ friq_connect(pi);
+ friq_read_block_int(pi,scratch,512,0x10);
+ r = 0;
+ for (k=0;k<128;k++) if (scratch[k] != k) r++;
+ friq_disconnect(pi);
+
+ if (verbose) {
+ printk("%s: friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
+ pi->device,pi->port,pi->mode,e[0],e[1],r);
+ }
+
+ return (r || (e[0] && e[1]));
+}
+
+
+static void friq_log_adapter( PIA *pi, char * scratch, int verbose )
+
+{ char *mode_string[6] = {"4-bit","8-bit",
+ "EPP-8","EPP-16","EPP-32"};
+
+ printk("%s: friq %s, Freecom IQ ASIC-2 adapter at 0x%x, ", pi->device,
+ FRIQ_VERSION,pi->port);
+ printk("mode %d (%s), delay %d\n",pi->mode,
+ mode_string[pi->mode],pi->delay);
+
+ pi->private = 1;
+ friq_connect(pi);
+ CMD(0x9e); /* disable sleep timer */
+ friq_disconnect(pi);
+
+}
+
+static void friq_init_proto( PIA *pi)
+
+{ MOD_INC_USE_COUNT;
+ pi->private = 0;
+}
+
+static void friq_release_proto( PIA *pi)
+
+{ if (pi->private) { /* turn off the power */
+ friq_connect(pi);
+ CMD(0x1d); CMD(0x1e);
+ friq_disconnect(pi);
+ pi->private = 0;
+ }
+
+ MOD_DEC_USE_COUNT;
+}
+
+struct pi_protocol friq = {"friq",0,5,2,1,1,
+ friq_write_regr,
+ friq_read_regr,
+ friq_write_block,
+ friq_read_block,
+ friq_connect,
+ friq_disconnect,
+ 0,
+ 0,
+ friq_test_proto,
+ friq_log_adapter,
+ friq_init_proto,
+ friq_release_proto
+ };
+
+
+#ifdef MODULE
+
+int init_module(void)
+
+{ return pi_register( &friq ) - 1;
+}
+
+void cleanup_module(void)
+
+{ pi_unregister( &friq );
+}
+
+#endif
+
+/* end of friq.c */
diff --git a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c
index 680f9e592..f4c98c645 100644
--- a/drivers/block/paride/frpw.c
+++ b/drivers/block/paride/frpw.c
@@ -5,6 +5,12 @@
frpw.c is a low-level protocol driver for the Freecom "Power"
parallel port IDE adapter.
+ Some applications of this adapter may require a "printer" reset
+ prior to loading the driver. This can be done by loading and
+ unloading the "lp" driver, or it can be done by this driver
+ if you define FRPW_HARD_RESET. The latter is not recommended
+ as it may upset devices on other ports.
+
*/
/* Changes:
@@ -13,10 +19,11 @@
fix chip detect
added EPP-16 and EPP-32
1.02 GRG 1998.09.23 added hard reset to initialisation process
+ 1.03 GRG 1998.12.14 made hard reset conditional
*/
-#define FRPW_VERSION "1.02"
+#define FRPW_VERSION "1.03"
#include <linux/module.h>
#include <linux/delay.h>
@@ -185,8 +192,10 @@ static int frpw_test_pnp ( PIA *pi )
{ int olddelay, a, b;
+#ifdef FRPW_HARD_RESET
w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */
mdelay(1500);
+#endif
olddelay = pi->delay;
pi->delay = 10;
diff --git a/drivers/block/paride/jumbo b/drivers/block/paride/jumbo
index b952fde92..f4b8ebf75 100644
--- a/drivers/block/paride/jumbo
+++ b/drivers/block/paride/jumbo
@@ -53,11 +53,11 @@ FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]`
FK="-D__KERNEL__ -I ../../../include"
FLCH=-D_LINUX_CONFIG_H
#
-echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
-cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+echo cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
+cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
#
-echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
-cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+echo cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
+cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
#
echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
diff --git a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c
index 78477593e..91dcad101 100644
--- a/drivers/block/paride/on26.c
+++ b/drivers/block/paride/on26.c
@@ -11,10 +11,12 @@
1.01 GRG 1998.05.06 init_proto, release_proto
1.02 GRG 1998.09.23 updates for the -E rev chip
+ 1.03 GRG 1998.12.14 fix for slave drives
+ 1.04 GRG 1998.12.20 yet another bug fix
*/
-#define ON26_VERSION "1.02"
+#define ON26_VERSION "1.04"
#include <linux/module.h>
#include <linux/delay.h>
@@ -118,9 +120,11 @@ static void on26_disconnect ( PIA *pi )
w2(pi->saved_r2);
}
+#define RESET_WAIT 200
+
static int on26_test_port( PIA *pi) /* hard reset */
-{ int i, m, d;
+{ int i, m, d, x, y;
pi->saved_r0 = r0();
pi->saved_r2 = r2();
@@ -151,11 +155,18 @@ static int on26_test_port( PIA *pi) /* hard reset */
on26_write_regr(pi,0,6,0xa0);
- for (i=0;i<100;i++) {
- if (!(on26_read_regr(pi,0,7) & 0x80)) break;
- udelay(100000);
+ for (i=0;i<RESET_WAIT;i++) {
+ on26_write_regr(pi,0,6,0xa0);
+ x = on26_read_regr(pi,0,7);
+ on26_write_regr(pi,0,6,0xb0);
+ y = on26_read_regr(pi,0,7);
+ if (!((x&0x80)||(y&0x80))) break;
+ mdelay(100);
}
+ if (i == RESET_WAIT)
+ printk("on26: Device reset failed (%x,%x)\n",x,y);
+
w0(4); P1; w0(4); P1;
}
@@ -189,7 +200,7 @@ static void on26_read_block( PIA *pi, char * buf, int count )
case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
udelay(10);
for (k=0;k<count/2;k++) {
- w2(0x26); buf[2*k] = r0();
+ w2(0x26); buf[2*k] = r0();
w2(0x24); buf[2*k+1] = r0();
}
w0(2); P1; w0(9); P2;
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 068deffd6..6e962d8c1 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -12,10 +12,11 @@
1.01 GRG 1998.05.03 Use spinlocks
1.02 GRG 1998.05.05 init_proto, release_proto, ktti
1.03 GRG 1998.08.15 eliminate compiler warning
+ 1.04 GRG 1998.11.28 added support for FRIQ
*/
-#define PI_VERSION "1.03"
+#define PI_VERSION "1.04"
#include <linux/module.h>
#include <linux/config.h>
@@ -450,6 +451,11 @@ void paride_init( void )
pi_register(&frpw);
};
#endif
+#ifdef CONFIG_PARIDE_FRIQ
+ { extern struct pi_protocol friq;
+ pi_register(&friq);
+ };
+#endif
#ifdef CONFIG_PARIDE_FIT2
{ extern struct pi_protocol fit2;
pi_register(&fit2);
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 1563a2afc..89c83db65 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -367,21 +367,21 @@ static int pg_wait( int unit, int go, int stop, int tmo, char * msg )
PG.status = 0;
j = 0;
- while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies<tmo)) {
+ while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(time_before(jiffies,tmo))) {
if (j++ < PG_SPIN) udelay(PG_SPIN_DEL);
else pg_sleep(1);
}
- if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) {
+ if ((r&(STAT_ERR&stop))||time_after_eq(jiffies, tmo)) {
s = RR(0,7);
e = RR(0,1);
p = RR(0,2);
if (verbose > 1)
printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
- PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":"");
+ PG.name,msg,s,e,p,time_after_eq(jiffies, tmo)?" timeout":"");
- if (jiffies>=tmo) e |= 0x100;
+ if (time_after_eq(jiffies, tmo)) e |= 0x100;
PG.status = (e >> 4) & 0xff;
return -1;
}
diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h
index 17615c2ca..3992f3c30 100644
--- a/drivers/block/paride/pseudo.h
+++ b/drivers/block/paride/pseudo.h
@@ -16,19 +16,21 @@
when either it returns true, or timeout jiffies have passed,
continuation() will be invoked.
- If nice is true, the test will done approximately once a
+ If nice is 1, the test will done approximately once a
jiffy. If nice is 0, the test will also be done whenever
- the scheduler runs (by adding it to a task queue).
+ the scheduler runs (by adding it to a task queue). If
+ nice is greater than 1, the test will be done once every
+ (nice-1) jiffies.
*/
/* Changes:
1.01 1998.05.03 Switched from cli()/sti() to spinlocks
-
+ 1.02 1998.12.14 Added support for nice > 1
*/
-#define PS_VERSION "1.01"
+#define PS_VERSION "1.02"
#include <linux/sched.h>
#include <linux/timer.h>
@@ -37,15 +39,15 @@
static void ps_timer_int( unsigned long data);
static void ps_tq_int( void *data);
-static int ps_use_tq = 1;
static void (* ps_continuation)(void);
static int (* ps_ready)(void);
static int ps_then;
static int ps_timeout;
static int ps_timer_active = 0;
static int ps_tq_active = 0;
+static int ps_nice = 0;
-static spinlock_t ps_spinlock = SPIN_LOCK_UNLOCKED;
+static spinlock_t ps_spinlock __attribute__((unused)) = SPIN_LOCK_UNLOCKED;
static struct timer_list ps_timer = {0,0,0,0,ps_timer_int};
static struct tq_struct ps_tq = {0,0,ps_tq_int,NULL};
@@ -62,9 +64,9 @@ static void ps_set_intr( void (*continuation)(void),
ps_ready = ready;
ps_then = jiffies;
ps_timeout = jiffies + timeout;
- ps_use_tq = !nice;
+ ps_nice = nice;
- if (ps_use_tq && !ps_tq_active) {
+ if (!ps_nice && !ps_tq_active) {
#ifdef HAVE_DISABLE_HLT
disable_hlt();
#endif
@@ -74,7 +76,7 @@ static void ps_set_intr( void (*continuation)(void),
if (!ps_timer_active) {
ps_timer_active = 1;
- ps_timer.expires = jiffies;
+ ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
add_timer(&ps_timer);
}
@@ -136,7 +138,7 @@ static void ps_timer_int( unsigned long data)
return;
}
ps_timer_active = 1;
- ps_timer.expires = jiffies;
+ ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
add_timer(&ps_timer);
spin_unlock_irqrestore(&ps_spinlock,flags);
}
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 1a09c84b0..2616319f7 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -471,7 +471,7 @@ static int pt_poll_dsc( int unit, int pause, int tmo, char *msg )
{ int k, e, s;
- k = 0;
+ k = 0; e = 0; s = 0;
while (k < tmo) {
pt_sleep(pause);
k++;
diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c
index b5b13b9cb..e032da579 100644
--- a/drivers/block/pdc4030.c
+++ b/drivers/block/pdc4030.c
@@ -92,13 +92,13 @@ int pdc4030_cmd(ide_drive_t *drive, byte cmd)
timeout = HZ * 10;
timeout += jiffies;
do {
- if(jiffies > timeout) {
+ if(time_after(jiffies, timeout)) {
return 2; /* device timed out */
}
/* This is out of delay_10ms() */
/* Delays at least 10ms to give interface a chance */
timer = jiffies + (HZ + 99)/100 + 1;
- while (timer > jiffies);
+ while (time_after(timer, jiffies));
status_val = IN_BYTE(IDE_SECTOR_REG);
} while (status_val != 0x50 && status_val != 0x70);
@@ -257,7 +257,7 @@ static void promise_write_pollfunc (ide_drive_t *drive)
struct request *rq;
if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
- if (jiffies < hwgroup->poll_timeout) {
+ if (time_before(jiffies, hwgroup->poll_timeout)) {
ide_set_handler (drive, &promise_write_pollfunc, 1);
return; /* continue polling... */
}
@@ -335,7 +335,7 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
if(IN_BYTE(IDE_SELECT_REG) & 0x01)
return;
udelay(1);
- } while (jiffies < timeout);
+ } while (time_before(jiffies, timeout));
printk("%s: reading: No DRQ and not waiting - Odd!\n",
drive->name);
return;
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 4e165bbd0..7c2d36c72 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -44,6 +44,7 @@
#include <linux/blk.h>
#include <linux/mca.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/system.h>
#include <asm/io.h>
diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c
index 12512c8df..890584dcd 100644
--- a/drivers/block/raid1.c
+++ b/drivers/block/raid1.c
@@ -309,8 +309,7 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh)
mirror_bh [i]->b_dev = bh->b_dev;
mirror_bh [i]->b_rdev = raid_conf->mirrors [i].dev;
mirror_bh [i]->b_rsector = bh->b_rsector;
- mirror_bh [i]->b_state = (1<<BH_Req) |
- (1<<BH_Touched) | (1<<BH_Dirty);
+ mirror_bh [i]->b_state = (1<<BH_Req) | (1<<BH_Dirty);
mirror_bh [i]->b_count = 1;
mirror_bh [i]->b_size = bh->b_size;
mirror_bh [i]->b_data = bh->b_data;
diff --git a/drivers/block/rz1000.c b/drivers/block/rz1000.c
index d1ae0a8b6..fe8c22900 100644
--- a/drivers/block/rz1000.c
+++ b/drivers/block/rz1000.c
@@ -5,7 +5,9 @@
*/
/*
- * Principal Author/Maintainer: mlord@pobox.com (Mark Lord)
+ * Principal Author: mlord@pobox.com (Mark Lord)
+ *
+ * See linux/MAINTAINERS for address of current maintainer.
*
* This file provides support for disabling the buggy read-ahead
* mode of the RZ1000 IDE chipset, commonly used on Intel motherboards.
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index 2ea4bf393..8adc37fcb 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -894,7 +894,7 @@ __initfunc(static void xd_wd_init_drive (u_char drive))
xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
}
- /* 1002 based RLL controler requests converted adressing, but reports physical
+ /* 1002 based RLL controler requests converted addressing, but reports physical
(physical 26 sec., logical 17 sec.)
1004 based ???? */
if (rll & wd_1002) {
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 193208d0d..f863a8326 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -14,6 +14,8 @@
** 37 0 Use Zorro II and Chip ram
** 37 1 Use only Zorro II ram
** 37 2 Use only Chip ram
+** 37 4-7 Use memory list entry 1-4 (first is 0)
+** ++jskov: support for 1-4th memory list entry.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
@@ -25,6 +27,7 @@
#define MAJOR_NR Z2RAM_MAJOR
+#include <linux/config.h>
#include <linux/major.h>
#include <linux/malloc.h>
#include <linux/blk.h>
@@ -37,23 +40,37 @@
#include <asm/setup.h>
#include <asm/bitops.h>
#include <asm/amigahw.h>
+#ifdef CONFIG_APUS
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#endif
#include <linux/zorro.h>
+
+extern int num_memory;
+extern struct mem_info memory[NUM_MEMINFO];
+
#define TRUE (1)
#define FALSE (0)
#define Z2MINOR_COMBINED (0)
#define Z2MINOR_Z2ONLY (1)
#define Z2MINOR_CHIPONLY (2)
+#define Z2MINOR_MEMLIST1 (4)
+#define Z2MINOR_MEMLIST2 (5)
+#define Z2MINOR_MEMLIST3 (6)
+#define Z2MINOR_MEMLIST4 (7)
+#define Z2MINOR_COUNT (8) /* Move this down when adding a new minor */
#define Z2RAM_CHUNK1024 ( Z2RAM_CHUNKSIZE >> 10 )
static u_long *z2ram_map = NULL;
static u_long z2ram_size = 0;
-static int z2_blocksizes[3] = { 1024, 1024, 1024 };
-static int z2_sizes[3] = { 0, 0, 0 };
+static int z2_blocksizes[Z2MINOR_COUNT];
+static int z2_sizes[Z2MINOR_COUNT];
static int z2_count = 0;
static int chip_count = 0;
+static int list_count = 0;
static int current_device = -1;
static void
@@ -166,8 +183,61 @@ z2_open( struct inode *inode, struct file *filp )
{
z2_count = 0;
chip_count = 0;
+ list_count = 0;
z2ram_size = 0;
+ /* Use a specific list entry. */
+ if (device >= Z2MINOR_MEMLIST1 && device <= Z2MINOR_MEMLIST4) {
+ int index = device - Z2MINOR_MEMLIST1 + 1;
+ unsigned long size, paddr, vaddr;
+
+ if (index >= num_memory) {
+ printk( KERN_ERR DEVICE_NAME
+ ": no such entry in z2ram_map\n" );
+ return -ENOMEM;
+ }
+
+ paddr = memory[index].addr;
+ size = memory[index].size & ~(Z2RAM_CHUNKSIZE-1);
+
+#ifdef __powerpc__
+ /* FIXME: ioremap doesn't build correct memory tables. */
+ {
+ extern void* vmalloc (unsigned long);
+ extern void vfree (void*);
+ vfree(vmalloc (size));
+ }
+
+ vaddr = (unsigned long) __ioremap (paddr, size,
+ _PAGE_WRITETHRU);
+
+#else
+ vaddr = kernel_map (paddr, size, KERNELMAP_FULL_CACHING,
+ NULL);
+#endif
+ z2ram_map =
+ kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]),
+ GFP_KERNEL);
+ if ( z2ram_map == NULL )
+ {
+ printk( KERN_ERR DEVICE_NAME
+ ": cannot get mem for z2ram_map\n" );
+ return -ENOMEM;
+ }
+
+ while (size) {
+ z2ram_map[ z2ram_size++ ] = vaddr;
+ size -= Z2RAM_CHUNKSIZE;
+ vaddr += Z2RAM_CHUNKSIZE;
+ list_count++;
+ }
+
+ if ( z2ram_size != 0 )
+ printk( KERN_INFO DEVICE_NAME
+ ": using %iK List Entry %d Memory\n",
+ list_count * Z2RAM_CHUNK1024, index );
+ } else
+
switch ( device )
{
case Z2MINOR_COMBINED:
@@ -253,12 +323,11 @@ z2_open( struct inode *inode, struct file *filp )
return 0;
}
-static void
+static int
z2_release( struct inode *inode, struct file *filp )
{
-
if ( current_device == -1 )
- return;
+ return 0;
sync_dev( inode->i_rdev );
@@ -266,7 +335,7 @@ z2_release( struct inode *inode, struct file *filp )
MOD_DEC_USE_COUNT;
#endif
- return;
+ return 0;
}
static struct file_operations z2_fops =
@@ -281,7 +350,10 @@ static struct file_operations z2_fops =
z2_open, /* open */
NULL, /* flush */
z2_release, /* release */
- block_fsync /* fsync */
+ block_fsync, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
};
__initfunc(int
@@ -297,6 +369,16 @@ z2_init( void ))
MAJOR_NR );
return -EBUSY;
}
+
+ {
+ /* Initialize size arrays. */
+ int i;
+
+ for (i = 0; i < Z2MINOR_COUNT; i++) {
+ z2_blocksizes[ i ] = 1024;
+ z2_sizes[ i ] = 0;
+ }
+ }
blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
blksize_size[ MAJOR_NR ] = z2_blocksizes;
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 85ed482b8..410c6e455 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1,7 +1,7 @@
/* linux/drivers/cdrom/cdrom.c.
Copyright (c) 1996, 1997 David A. van Leeuwen.
Copyright (c) 1997, 1998 Erik Andersen <andersee@debian.org>
- Copyright (c) 1998 Jens Axboe and Chris Zwilling
+ Copyright (c) 1998, 1999 Jens Axboe
May be copied or modified under the terms of the GNU General Public
License. See linux/COPYING for more information.
@@ -87,15 +87,27 @@
Thanks to Grant R. Guenther <grant@torque.net> for spotting this bug.
-- Made a few things more pedanticly correct.
- 2.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk>
+2.50 Oct 19, 1998 - Jens Axboe <axboe@image.dk>
-- New maintainers! Erik was too busy to continue the work on the driver,
so now Chris Zwilling <chris@cloudnet.com> and Jens Axboe <axboe@image.dk>
will do their best to follow in his footsteps
+
+ 2.51 Dec 20, 1998 - Jens Axboe <axboe@image.dk>
+ -- Check if drive is capable of doing what we ask before blindly changing
+ cdi->options in various ioctl.
+ -- Added version to proc entry.
+
+ 2.52 Jan 16, 1998 - Jens Axboe <axboe@image.dk>
+ -- Fixed an error in open_for_data where we would sometimes not return
+ the correct error value. Thanks Huba Gaspar <huba@softcell.hu>.
+ -- Fixed module usage count - usage was based on /proc/sys/dev
+ instead of /proc/sys/dev/cdrom. This could lead to an oops when other
+ modules had entries in dev.
-------------------------------------------------------------------------*/
-#define REVISION "Revision: 2.50"
-#define VERSION "Id: cdrom.c 2.50 1998/10/19"
+#define REVISION "Revision: 2.52"
+#define VERSION "Id: cdrom.c 2.52 1999/01/16"
/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
@@ -211,6 +223,8 @@ int register_cdrom(struct cdrom_device_info *cdi)
struct cdrom_device_ops *cdo = cdi->ops;
int *change_capability = (int *)&cdo->capability; /* hack */
+ cdinfo(CD_OPEN, "entering register_cdrom\n");
+
if (major < 0 || major >= MAX_BLKDEV)
return -1;
if (cdo->open == NULL || cdo->release == NULL)
@@ -236,9 +250,10 @@ int register_cdrom(struct cdrom_device_info *cdi)
cdi->mc_flags = 0;
cdo->n_minors = 0;
cdi->options = CDO_USE_FFLAGS;
- if (autoclose==1)
+
+ if (autoclose==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
cdi->options |= (int) CDO_AUTO_CLOSE;
- if (autoeject==1)
+ if (autoeject==1 && cdo->capability & ~cdi->mask & CDC_OPEN_TRAY)
cdi->options |= (int) CDO_AUTO_EJECT;
if (lockdoor==1)
cdi->options |= (int) CDO_LOCK;
@@ -257,6 +272,8 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
struct cdrom_device_info *cdi, *prev;
int major = MAJOR (unreg->dev);
+ cdinfo(CD_OPEN, "entering unregister_cdrom\n");
+
if (major < 0 || major >= MAX_BLKDEV)
return -1;
@@ -353,7 +370,7 @@ int open_for_data(struct cdrom_device_info * cdi)
goto clean_up_and_return;
}
} else {
- cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n");
+ cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n");
ret=-ENOMEDIUM;
goto clean_up_and_return;
}
@@ -361,13 +378,16 @@ int open_for_data(struct cdrom_device_info * cdi)
ret = cdo->drive_status(cdi, CDSL_CURRENT);
if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n");
+ cdinfo(CD_OPEN, "tray might not contain a medium.\n");
ret=-ENOMEDIUM;
goto clean_up_and_return;
}
cdinfo(CD_OPEN, "the tray is now closed.\n");
}
- if (ret!=CDS_DISC_OK)
+ if (ret!=CDS_DISC_OK) {
+ ret = -ENOMEDIUM;
goto clean_up_and_return;
+ }
}
cdrom_count_tracks(cdi, &tracks);
if (tracks.error == CDS_NO_DISC) {
@@ -405,7 +425,7 @@ int open_for_data(struct cdrom_device_info * cdi)
cdo->lock_door(cdi, 1);
cdinfo(CD_OPEN, "door locked.\n");
}
- cdinfo(CD_OPEN, "device opened sucessfully.\n");
+ cdinfo(CD_OPEN, "device opened successfully.\n");
return ret;
/* Something failed. Try to unlock the drive, because some drivers
@@ -687,7 +707,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
sanitize_format(&ms_info.addr, &ms_info.addr_format,
requested_format);
IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
- cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION sucessful\n");
+ cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
return 0;
}
@@ -713,6 +733,8 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
case CDROMEJECT_SW:
cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
+ if (!(cdo->capability & ~cdi->mask & CDC_OPEN_TRAY))
+ return -ENOSYS;
cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
if (arg)
cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
@@ -733,6 +755,8 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
case CDROM_SET_OPTIONS:
cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
+ if (cdo->capability & arg & ~cdi->mask)
+ return -ENOSYS;
cdi->options |= (int) arg;
return cdi->options;
@@ -773,7 +797,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
if ((ret=cdo->get_mcn(cdi, &mcn)))
return ret;
IOCTL_OUT(arg, struct cdrom_mcn, mcn);
- cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN sucessful\n");
+ cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
return 0;
}
@@ -879,7 +903,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
sanitize_format(&q.cdsc_absaddr, &back, requested);
sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
IOCTL_OUT(arg, struct cdrom_subchnl, q);
- /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL sucessful\n"); */
+ /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
return 0;
}
case CDROMREADTOCHDR: {
@@ -892,7 +916,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
return ret;
IOCTL_OUT(arg, struct cdrom_tochdr, header);
- /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR sucessful\n"); */
+ /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
return 0;
}
case CDROMREADTOCENTRY: {
@@ -914,7 +938,7 @@ int cdrom_ioctl(struct inode *ip, struct file *fp,
sanitize_format(&entry.cdte_addr,
&entry.cdte_format, requested_format);
IOCTL_OUT(arg, struct cdrom_tocentry, entry);
- /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY sucessful\n"); */
+ /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
return 0;
}
case CDROMPLAYMSF: {
@@ -981,10 +1005,15 @@ static char cdrom_drive_info[CDROM_STR_SIZE]="info\n";
int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
void *buffer, size_t *lenp)
{
- int retv,pos;
+ int pos;
struct cdrom_device_info *cdi;
+
+ if (!*lenp || (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
- pos = sprintf(cdrom_drive_info, "CD-ROM information\n");
+ pos = sprintf(cdrom_drive_info, "CD-ROM information, " VERSION "\n");
pos += sprintf(cdrom_drive_info+pos, "\ndrive name:\t");
for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next)
@@ -1045,18 +1074,14 @@ int cdrom_sysctl_info(ctl_table *ctl, int write, struct file * filp,
strcpy(cdrom_drive_info+pos,"\n\n");
*lenp=pos+3;
- if (!write) {
- retv = proc_dostring(ctl, write, filp, buffer, lenp);
- }
- else
- retv = proc_dostring(ctl, write, filp, buffer, lenp);
- return retv;
+
+ return proc_dostring(ctl, write, filp, buffer, lenp);
}
/* Place files in /proc/sys/dev/cdrom */
ctl_table cdrom_table[] = {
{DEV_CDROM_INFO, "info", &cdrom_drive_info,
- CDROM_STR_SIZE*sizeof(char), 0444, NULL, &cdrom_sysctl_info},
+ CDROM_STR_SIZE, 0444, NULL, &cdrom_sysctl_info},
{0}
};
@@ -1083,20 +1108,23 @@ static struct ctl_table_header *cdrom_sysctl_header;
*/
static void cdrom_procfs_modcount(struct inode *inode, int fill)
{
- if (fill)
- MOD_INC_USE_COUNT;
- else
- MOD_DEC_USE_COUNT;
+ if (fill) {
+ MOD_INC_USE_COUNT;
+ } else {
+ MOD_DEC_USE_COUNT;
+ }
}
static void cdrom_sysctl_register(void)
{
static int initialized = 0;
- if ( initialized == 1 )
+ if (initialized == 1)
return;
- cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 0);
+
+ cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
cdrom_root_table->de->fill_inode = &cdrom_procfs_modcount;
+
initialized = 1;
}
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
index 7bafb457a..d893cdecd 100644
--- a/drivers/cdrom/cdu31a.c
+++ b/drivers/cdrom/cdu31a.c
@@ -32,7 +32,7 @@
* the following:
*
* retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- * while ((retry_count > jiffies) && (! <some condition to wait for))
+ * while (time_before(jiffies, retry_count) && (! <some condition to wait for))
* {
* while (handle_sony_cd_attention())
* ;
@@ -488,7 +488,7 @@ static int scd_reset(struct cdrom_device_info * cdi)
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
- while ((retry_count > jiffies) && (!is_attention()))
+ while (time_before(jiffies, retry_count) && (!is_attention()))
{
sony_sleep();
}
@@ -740,7 +740,7 @@ restart_on_error(void)
printk("cdu31a: Resetting drive on error\n");
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
- while ((retry_count > jiffies) && (!is_attention()))
+ while (time_before(jiffies, retry_count) && (!is_attention()))
{
sony_sleep();
}
@@ -808,7 +808,7 @@ get_result(unsigned char *result_buffer,
;
/* Wait for the result data to be ready */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while ((retry_count > jiffies) && (is_busy() || (!(is_result_ready()))))
+ while (time_before(jiffies, retry_count) && (is_busy() || (!(is_result_ready()))))
{
sony_sleep();
@@ -978,7 +978,7 @@ retry_cd_operation:
sti();
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while ((retry_count > jiffies) && (is_busy()))
+ while (time_before(jiffies, retry_count) && (is_busy()))
{
sony_sleep();
@@ -1246,7 +1246,7 @@ start_request(unsigned int sector,
;
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while ((retry_count > jiffies) && (is_busy()))
+ while (time_before(jiffies, retry_count) && (is_busy()))
{
sony_sleep();
@@ -1514,7 +1514,7 @@ read_data_block(char *buffer,
/* Wait for the drive to tell us we have something */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while ((retry_count > jiffies) && !(is_data_ready()))
+ while (time_before(jiffies, retry_count) && !(is_data_ready()))
{
while (handle_sony_cd_attention())
;
@@ -1553,7 +1553,7 @@ read_data_block(char *buffer,
/* Wait for the status from the drive. */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while ((retry_count > jiffies) && !(is_result_ready()))
+ while (time_before(jiffies, retry_count) && !(is_result_ready()))
{
while (handle_sony_cd_attention())
;
@@ -2432,8 +2432,7 @@ read_audio_data(char *buffer,
/* Wait for the drive to tell us we have something */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
continue_read_audio_wait:
- while ( (retry_count > jiffies)
- && !(is_data_ready())
+ while (time_before(jiffies, retry_count) && !(is_data_ready())
&& !(is_result_ready() || result_read))
{
while (handle_sony_cd_attention())
@@ -2495,7 +2494,7 @@ continue_read_audio_wait:
{
/* Wait for the drive to tell us we have something */
retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
- while ((retry_count > jiffies) && !(is_result_ready()))
+ while (time_before(jiffies, retry_count) && !(is_result_ready()))
{
while (handle_sony_cd_attention())
;
@@ -3286,7 +3285,7 @@ get_drive_configuration(unsigned short base_io,
*/
reset_drive();
retry_count = jiffies + SONY_RESET_TIMEOUT;
- while ((retry_count > jiffies) && (!is_attention()))
+ while (time_before(jiffies, retry_count) && (!is_attention()))
{
sony_sleep();
}
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index 121550cc3..708b72833 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -1778,7 +1778,7 @@ mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char* buf)
if (!buf) buf = &c;
while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {
- if (jiffies > timeout) return -1;
+ if (time_after(jiffies, timeout)) return -1;
mcdx_delay(stuffp, delay);
}
diff --git a/drivers/cdrom/mcdx.h b/drivers/cdrom/mcdx.h
index b1b431326..ac3c8c85b 100644
--- a/drivers/cdrom/mcdx.h
+++ b/drivers/cdrom/mcdx.h
@@ -77,7 +77,6 @@
/* *** make the following line uncommented, if you're sure,
* *** all configuration is done */
/* #define I_WAS_HERE */
-#define I_WAS_HERE /* delete this line, it's for heiko only */
/* The name of the device */
#define MCDX "mcdx"
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 8c7592146..73750c56c 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -1014,20 +1014,20 @@ static int CDi_stat_loop_T(void)
{
case 4:
sbp_sleep(HZ);
- if (jiffies > timeout_4) gear++;
+ if (time_after(jiffies, timeout_4)) gear++;
msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
break;
case 3:
sbp_sleep(HZ/10);
- if (jiffies > timeout_3) gear++;
+ if (time_after(jiffies, timeout_3)) gear++;
break;
case 2:
sbp_sleep(HZ/100);
- if (jiffies > timeout_2) gear++;
+ if (time_after(jiffies, timeout_2)) gear++;
break;
case 1:
sbp_sleep(0);
- if (jiffies > timeout_1) gear++;
+ if (time_after(jiffies, timeout_1)) gear++;
}
} while (gear < 5);
return -1;
@@ -1037,7 +1037,7 @@ static int CDi_stat_loop(void)
{
int i,j;
- for(timeout = jiffies + 10*HZ, i=maxtim_data; timeout > jiffies; )
+ for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
{
for ( ;i!=0;i--)
{
@@ -1098,11 +1098,11 @@ static int ResponseInfo(void)
st=inb(CDi_status);
if (!(st&s_not_result_ready)) break;
}
- if ((j!=0)||(timeout<=jiffies)) break;
+ if ((j!=0)||time_after_eq(jiffies, timeout)) break;
sbp_sleep(1);
j = 1;
}
- if (timeout<=jiffies) break;
+ if (time_after_eq(jiffies, timeout)) break;
infobuf[i]=inb(CDi_info);
}
#if 000
@@ -1238,7 +1238,7 @@ static int ResponseStatus(void)
i=inb(CDi_status);
if (!(i&s_not_result_ready)) break;
}
- if ((j!=0)||(timeout<jiffies)) break;
+ if ((j!=0)||time_after(jiffies, timeout)) break;
sbp_sleep(1);
j = 1;
}
@@ -4355,7 +4355,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
if (!(j&s_not_result_ready)) break;
if (fam0L_drive) if (j&s_attention) break;
}
- if (try != 0 || timeout <= jiffies) break;
+ if (try != 0 || time_after_eq(jiffies, timeout)) break;
if (data_retrying == 0) data_waits++;
data_retrying = 1;
sbp_sleep(1);
@@ -4419,7 +4419,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
if (fam0L_drive)
{
i=maxtim_data;
- for (timeout=jiffies+9*HZ; timeout > jiffies; timeout--)
+ for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
{
for ( ;i!=0;i--)
{
@@ -4428,7 +4428,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
if (!(j&s_not_result_ready)) break;
if (j&s_attention) break;
}
- if (i != 0 || timeout <= jiffies) break;
+ if (i != 0 || time_after_eq(jiffies, timeout)) break;
sbp_sleep(0);
i = 1;
}
@@ -5250,7 +5250,7 @@ static int sbp_data(struct request *req)
{
SBPCD_CLI;
i=maxtim_data;
- for (timeout=jiffies+HZ; timeout > jiffies; timeout--)
+ for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
{
for ( ;i!=0;i--)
{
@@ -5259,7 +5259,7 @@ static int sbp_data(struct request *req)
if (!(j&s_not_result_ready)) break;
if (j&s_attention) break;
}
- if (i != 0 || timeout <= jiffies) break;
+ if (i != 0 || time_after_eq(jiffies, timeout)) break;
sbp_sleep(0);
i = 1;
}
@@ -5701,7 +5701,7 @@ __initfunc(int SBPCD_INIT(void))
if (i<0) break;
if (!st_caddy_in) break;
}
- while ((!st_diskok)||(timeout<jiffies));
+ while ((!st_diskok)||time_after(jiffies, timeout));
}
i=SetSpeed();
if (i>=0) D_S[j].CD_changed=1;
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 6681f2a19..631dbffa6 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -1488,7 +1488,7 @@ __initfunc(int sjcd_init( void )){
/*
* Wait 10ms approx.
*/
- for( timer = jiffies; jiffies <= timer; );
+ for( timer = jiffies; time_before_eq(jiffies, timer); );
if ( (i % 100) == 0 ) printk( "." );
( void )sjcd_check_status();
}
@@ -1509,7 +1509,7 @@ __initfunc(int sjcd_init( void )){
/*
* Wait 10ms approx.
*/
- for( timer = jiffies; jiffies <= timer; );
+ for( timer = jiffies; time_before_eq(jiffies, timer); );
if ( (i % 100) == 0 ) printk( "." );
( void )sjcd_check_status();
}
@@ -1540,7 +1540,7 @@ __initfunc(int sjcd_init( void )){
/*
* Wait 10ms approx.
*/
- for( timer = jiffies; jiffies <= timer; );
+ for( timer = jiffies; time_before_eq(jiffies, timer); );
if ( (i % 100) == 0 ) printk( "." );
( void )sjcd_check_status();
}
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index f9a321b6f..f16b5b1d0 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -151,6 +151,8 @@
# define CDU535_MESSAGE_NAME "Sony CDU-535"
#endif
+#define CDU535_BLOCK_SIZE 2048
+
#ifndef MAX_SPINUP_RETRY
# define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
#endif
@@ -591,7 +593,6 @@ static int
seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
Byte **buff, int buf_size)
{
- const int block_size = 2048;
Byte cmd_buff[7];
int i;
int read_status;
@@ -599,7 +600,7 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
Byte *data_buff;
int sector_count = 0;
- if (buf_size < ((long)block_size) * n_blocks)
+ if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
return NO_ROOM;
set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
@@ -625,7 +626,7 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
/* data is ready, read it */
data_buff = buff[sector_count++];
- for (i = 0; i < block_size; i++)
+ for (i = 0; i < CDU535_BLOCK_SIZE; i++)
*data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
data_valid = 1;
break; /* exit the timeout loop */
@@ -639,7 +640,7 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
/* read all the data, now read the status */
if ((i = read_exec_status(status)) != 0)
return i;
- return block_size * sector_count;
+ return CDU535_BLOCK_SIZE * sector_count;
} /* seek_and_read_N_blocks() */
/****************************************************************************
@@ -776,7 +777,7 @@ size_to_buf(unsigned int size, Byte *buf)
* The OS calls this to perform a read or write operation to the drive.
* Write obviously fail. Reads to a read ahead of sony_buffer_size
* bytes to help speed operations. This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
+ * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most
* data access on a CD is done sequentially, this saves a lot of operations.
*/
static void
@@ -873,7 +874,7 @@ do_cdu535_request(void)
* seek_and_read_N_blocks for the various cases.
*/
int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * 2048));
+ status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
if (0 <= readStatus) /* Good data; common case, placed first */
break;
if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
@@ -1480,6 +1481,8 @@ static struct file_operations cdu_fops =
NULL /* revalidate */
};
+static int sonycd535_block_size = CDU535_BLOCK_SIZE;
+
/*
* Initialize the driver.
*/
@@ -1580,7 +1583,7 @@ sony535_init(void))
if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
/* set the drive mode successful, we are set! */
sony_buffer_size = SONY535_BUFFER_SIZE;
- sony_buffer_sectors = sony_buffer_size / 2048;
+ sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
drive_config.vendor_id,
@@ -1597,6 +1600,7 @@ sony535_init(void))
return -EIO;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = &sonycd535_block_size;
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
sony_toc = (struct s535_sony_toc *)
@@ -1617,7 +1621,8 @@ sony535_init(void))
return -ENOMEM;
}
for (i = 0; i < sony_buffer_sectors; i++) {
- sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL);
+ sony_buffer[i] =
+ (Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
if (sony_buffer[i] == NULL) {
while (--i>=0)
kfree(sony_buffer[i]);
@@ -1680,7 +1685,7 @@ cleanup_module(void)
release_region(sony535_cd_base_io, 4);
for (i = 0; i < sony_buffer_sectors; i++)
- kfree_s(sony_buffer[i], 2048);
+ kfree_s(sony_buffer[i], CDU535_BLOCK_SIZE);
kfree_s(sony_buffer, 4 * sony_buffer_sectors);
kfree_s(last_sony_subcode, sizeof *last_sony_subcode);
kfree_s(sony_toc, sizeof *sony_toc);
diff --git a/drivers/char/Config.in b/drivers/char/Config.in
index a81a95013..6967c30e2 100644
--- a/drivers/char/Config.in
+++ b/drivers/char/Config.in
@@ -35,10 +35,13 @@ if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
fi
tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8
tristate 'Specialix IO8+ card support' CONFIG_SPECIALIX
- if [ "$CONFIG_SPECIALIX" = "y" -o "$CONFIG_SPECIALIX" = "m" ]; then
+ if [ "$CONFIG_SPECIALIX" != "n" ]; then
bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
fi
tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m
+ fi
fi
bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
@@ -53,12 +56,19 @@ fi
bool 'Mouse Support (not serial mice)' CONFIG_MOUSE
if [ "$CONFIG_MOUSE" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Mice'
tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE
tristate 'Logitech busmouse support' CONFIG_BUSMOUSE
tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE
bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
tristate 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE
tristate 'PC110 digitizer pad support' CONFIG_PC110_PAD
+ endmenu
+fi
+
+if [ "$CONFIG_SGI" = "y" ]; then
+ bool 'Support for SGI graphic devices' CONFIG_SGI_GRAPHICS
fi
tristate 'QIC-02 tape support' CONFIG_QIC02_TAPE
@@ -69,12 +79,14 @@ if [ "$CONFIG_QIC02_TAPE" != "n" ]; then
else
comment ' Setting runtime QIC-02 configuration is done with qic02conf'
comment ' from the tpqic02-support package. It is available at'
- comment ' sunsite.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
+ comment ' metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/'
fi
fi
bool 'Watchdog Timer Support' CONFIG_WATCHDOG
if [ "$CONFIG_WATCHDOG" != "n" ]; then
+ mainmenu_option next_comment
+ comment 'Watchdog Cards'
bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
tristate ' WDT Watchdog timer' CONFIG_WDT
if [ "$CONFIG_WDT" != "n" ]; then
@@ -86,12 +98,19 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG
tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG
tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT
+ endmenu
fi
+
+
+tristate '/dev/nvram support' CONFIG_NVRAM
bool 'Enhanced Real Time Clock Support' CONFIG_RTC
if [ "$CONFIG_ALPHA_BOOK1" = "y" ]; then
bool 'Tadpole ANA H8 Support' CONFIG_H8
fi
+mainmenu_option next_comment
+comment 'Video For Linux'
+
tristate 'Video For Linux' CONFIG_VIDEO_DEV
if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
dep_tristate 'AIMSlab RadioTrack (aka RadioReveal) support' CONFIG_RADIO_RTRACK $CONFIG_VIDEO_DEV
@@ -107,7 +126,13 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
hex ' Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
fi
dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
- dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+ dep_tristate 'GemTek Radio Card support' CONFIG_RADIO_GEMTEK $CONFIG_VIDEO_DEV
+ if [ "$CONFIG_RADIO_GEMTEK" = "y" ]; then
+ hex ' GemTek i/o port (0x20c, 0x30c, 0x24c or 0x34c)' CONFIG_RADIO_GEMTEK_PORT 34c
+ fi
+ if [ "$CONFIG_PCI" != "n" ]; then
+ dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+ fi
if [ "$CONFIG_PARPORT" != "n" ]; then
dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV
dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV
@@ -128,11 +153,18 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
hex ' ZOLTRIX I/O port (0x20c or 0x30c)' CONFIG_RADIO_ZOLTRIX_PORT 20c
fi
fi
-tristate '/dev/nvram support' CONFIG_NVRAM
+
+endmenu
+
+mainmenu_option next_comment
+comment 'Joystick support'
+
tristate 'Joystick support' CONFIG_JOYSTICK
if [ "$CONFIG_JOYSTICK" != "n" ]; then
source drivers/char/joystick/Config.in
fi
+endmenu
+
mainmenu_option next_comment
comment 'Ftape, the floppy tape device driver'
tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index af9983701..7544ffb4a 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -122,6 +122,14 @@ else
endif
endif
+ifeq ($(CONFIG_ISI),y)
+L_OBJS += isicom.o
+else
+ ifeq ($(CONFIG_ISI),m)
+ M_OBJS += isicom.o
+ endif
+endif
+
ifeq ($(CONFIG_ESPSERIAL),y)
L_OBJS += esp.o
else
@@ -384,6 +392,14 @@ else
endif
endif
+ifeq ($(CONFIG_RADIO_GEMTEK),y)
+L_OBJS += radio-gemtek.o
+else
+ ifeq ($(CONFIG_RADIO_GEMTEK),m)
+ M_OBJS += radio-gemtek.o
+ endif
+endif
+
ifeq ($(CONFIG_QIC02_TAPE),y)
L_OBJS += tpqic02.o
else
diff --git a/drivers/char/README.epca b/drivers/char/README.epca
index 0efccae58..ac91d56dd 100644
--- a/drivers/char/README.epca
+++ b/drivers/char/README.epca
@@ -155,7 +155,7 @@ The four user programs listed below are described in this document:
current digiConfig application does not provide this function for PCI cards
(Though it does build device nodes for non-PCI cards). To use this program
execute the following:first install the driver, and execute digiDload (See above). After digiDload
- has sucessfully loaded, execute the following:
+ has successfully loaded, execute the following:
buildPCI <arg1> <arg2>
@@ -295,7 +295,7 @@ Description (Verbose) : Made the following modifications:
Linux kernels support higher baud rates by using
0x1000 bit. When the returned value (ored with
0x1000) was used to reference our fbaud table a
- serious memory problem occured. This has been fixed.
+ serious memory problem occurred. This has been fixed.
4. Added a request_region call to post_fep_init. This
should cause the i/o ports being used to be
@@ -401,8 +401,8 @@ Description (Verbose) : Made the following modifications:
found in epcaconfig.h; if so it DOESN'T load
epcaconfig data depending on epca_setup to handle
board configuration. pc_open has been modified
- such that it checks to insure that no errors
- occured during the LILO boot process. If a
+ such that it checks to ensure that no errors
+ occurred during the LILO boot process. If a
user attempts to boot the driver (via. LILO)
with incorrect data, the open will fail.
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c
index de2d25b0e..90c117467 100644
--- a/drivers/char/bttv.c
+++ b/drivers/char/bttv.c
@@ -17,66 +17,87 @@
You 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.
-
- Modified to put the RISC code writer in the kernel and to fit a
- common (and I hope safe) kernel interface. When we have an X extension
- all will now be really sweet.
-
- TODO:
-
- * move norm from tuner to channel struct!?
- composite source from a satellite tuner can deliver different norms
- depending on tuned channel
- * mmap VBI data?
- * fix RAW Composite grabbing for NTSC
- * fix VBI reading double frames when grabbing is active
- * allow for different VDELAYs
- * extra modules for tda9850, tda8425, any volunteers???
*/
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/malloc.h>
-#include <linux/vmalloc.h>
#include <linux/mm.h>
+#if LINUX_VERSION_CODE >= 0x020100
+#include <linux/poll.h>
+#endif
#include <linux/pci.h>
#include <linux/signal.h>
#include <asm/io.h>
+#include <linux/ioport.h>
#include <asm/pgtable.h>
#include <asm/page.h>
#include <linux/sched.h>
#include <asm/segment.h>
#include <linux/types.h>
#include <linux/wrapper.h>
-
-#include <linux/videodev.h>
+#include <linux/interrupt.h>
#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= 0x020100
#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#else
+#include <linux/bios32.h>
+#define mdelay(x) udelay((x)*1000)
+#define signal_pending(current) (current->signal & ~current->blocked)
+#define sigfillset(set)
+
+static inline int time_before(unsigned long a, unsigned long b)
+{
+ return((long)((a) - (b)) < 0L);
+}
+static inline unsigned long
+copy_to_user(void *to, const void *from, unsigned long n)
+{
+ memcpy_tofs(to,from,n);
+ return 0;
+}
+
+static inline unsigned long
+copy_from_user(void *to, const void *from, unsigned long n)
+{
+ memcpy_fromfs(to,from,n);
+ return 0;
+}
+#define ioremap vremap
+#define iounmap vfree
+#endif
+
+#include <linux/videodev.h>
#include <linux/i2c.h>
#include "bttv.h"
#include "tuner.h"
-#define DEBUG(x) /* Debug driver */
+#define DEBUG(x) /* Debug driver */
#define IDEBUG(x) /* Debug interrupt handler */
+#if LINUX_VERSION_CODE >= 0x020117
MODULE_PARM(vidmem,"i");
MODULE_PARM(triton1,"i");
MODULE_PARM(remap,"1-4i");
MODULE_PARM(radio,"1-4i");
MODULE_PARM(card,"1-4i");
MODULE_PARM(pll,"1-4i");
-
-static int find_vga(void);
-static void bt848_set_risc_jmps(struct bttv *btv);
+#endif
/* Anybody who uses more than four? */
#define BTTV_MAX 4
+static int find_vga(void);
+static void bt848_set_risc_jmps(struct bttv *btv);
+
static unsigned int vidmem=0; /* manually set video mem address */
static int triton1=0;
#ifndef USE_PLL
@@ -103,9 +124,11 @@ static struct bttv bttvs[BTTV_MAX];
{ btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
#define I2C_GET() (btread(BT848_I2C)&1)
-#define EEPROM_WRITE_DELAY 20000
+#define EEPROM_WRITE_DELAY 20000
#define BURSTOFFSET 76
+
+
/*******************************/
/* Memory management functions */
/*******************************/
@@ -190,6 +213,8 @@ static void rvfree(void * mem, unsigned long size)
}
}
+
+
/*
* Create the giant waste of buffer space we need for now
* until we get DMA to user space sorted out (probably 2.3.x)
@@ -387,7 +412,9 @@ static struct i2c_bus bttv_i2c_bus_template =
I2C_BUSID_BT848,
NULL,
+#if LINUX_VERSION_CODE >= 0x020100
SPIN_LOCK_UNLOCKED,
+#endif
attach_inform,
detach_inform,
@@ -399,6 +426,70 @@ static struct i2c_bus bttv_i2c_bus_template =
};
/* ----------------------------------------------------------------------- */
+/* some hauppauge specific stuff */
+
+static unsigned char eeprom_data[256];
+static struct HAUPPAUGE_TUNER
+{
+ int id;
+ char *name;
+}
+hauppauge_tuner[] =
+{
+ { TUNER_ABSENT, "" },
+ { TUNER_ABSENT, "External" },
+ { TUNER_ABSENT, "Unspecified" },
+ { TUNER_ABSENT, "Philips FI1216" },
+ { TUNER_ABSENT, "Philips FI1216MF" },
+ { TUNER_PHILIPS_NTSC, "Philips FI1236" },
+ { TUNER_ABSENT, "Philips FI1246" },
+ { TUNER_ABSENT, "Philips FI1256" },
+ { TUNER_PHILIPS_PAL, "Philips FI1216 MK2" },
+ { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
+ { TUNER_PHILIPS_NTSC, "Philips FI1236 MK2" },
+ { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
+ { TUNER_ABSENT, "Philips FI1256 MK2" },
+ { TUNER_ABSENT, "Temic 4032FY5" },
+ { TUNER_TEMIC_PAL, "Temic 4002FH5" },
+ { TUNER_TEMIC_PAL_I, "Temic 4062FY5" },
+ { TUNER_ABSENT, "Philips FR1216 MK2" },
+ { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
+ { TUNER_PHILIPS_NTSC, "Philips FR1236 MK2" },
+ { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
+ { TUNER_ABSENT, "Philips FR1256 MK2" },
+ { TUNER_PHILIPS_PAL, "Philips FM1216" },
+ { TUNER_ABSENT, "Philips FM1216MF" },
+ { TUNER_PHILIPS_NTSC, "Philips FM1236" },
+};
+
+static void
+hauppauge_eeprom(struct i2c_bus *bus)
+{
+ struct bttv *btv = (struct bttv*)bus->data;
+
+ readee(bus, eeprom_data);
+ if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
+ {
+ btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id;
+ printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr,
+ hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type);
+ }
+}
+
+static void
+hauppauge_msp_reset(struct bttv *btv)
+{
+ /* Reset the MSP on some Hauppauge cards */
+ /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */
+ /* Can this hurt cards without one? What about Miros with MSP? */
+ btaor(32, ~32, BT848_GPIO_OUT_EN);
+ btaor(0, ~32, BT848_GPIO_DATA);
+ udelay(2500);
+ btaor(32, ~32, BT848_GPIO_DATA);
+ /* btaor(0, ~32, BT848_GPIO_OUT_EN); */
+}
+
+/* ----------------------------------------------------------------------- */
struct tvcard
@@ -436,25 +527,19 @@ static struct tvcard tvcards[] =
{0, 0xc00, 0x800, 0x400, 0xc00, 0}},
/* TurboTV */
{ 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
- /* Newer Hauppauge (bt878) */
+ /* Newer Hauppauge (bt878) */
{ 3, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4}},
- /* MIRO PCTV pro */
- { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
+ /* MIRO PCTV pro */
+ { 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10}},
/* ADS Technologies Channel Surfer TV (and maybe TV+FM) */
- {
- 3, 4, 0, 2, 0x0F,
- { 0x02, 0x03, 0x01, 0x01},
- { 0x0D, 0x0E, 0x0B, 0x07, 0x00, 0x00},
- 0x00
- },
+ { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
+ /* AVerMedia TVCapture 98 */
+ { 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0}, 0},
+ /* Aimslab VHX */
+ { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
};
#define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
-
-/*
- * Tuner, Radio, internal, external and mute
- */
-
static void audio(struct bttv *btv, int mode)
{
btaor(tvcards[btv->type].gpiomask, ~tvcards[btv->type].gpiomask,
@@ -542,16 +627,16 @@ static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
fout*=12;
fi=fout/fin;
- fout=(fout-fin*fi)*256;
+ fout=(fout%fin)*256;
fh=fout/fin;
- fout=(fout-fin*fh)*256;
+ fout=(fout%fin)*256;
fl=fout/fin;
/*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/
- btwrite(fl,BT848_PLL_F_LO);
- btwrite(fh,BT848_PLL_F_HI);
- btwrite(fi|BT848_PLL_X,BT848_PLL_XCI);
+ btwrite(fl, BT848_PLL_F_LO);
+ btwrite(fh, BT848_PLL_F_HI);
+ btwrite(fi|BT848_PLL_X, BT848_PLL_XCI);
}
static int set_pll(struct bttv *btv)
@@ -593,7 +678,7 @@ static int set_pll(struct bttv *btv)
}
while(time_before(jiffies,tv));
- for (i=0; i<100; i++)
+ for (i=0; i<10; i++)
{
if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))
btwrite(0,BT848_DSTATUS);
@@ -614,13 +699,14 @@ static int set_pll(struct bttv *btv)
static void bt848_muxsel(struct bttv *btv, unsigned int input)
{
btaor(tvcards[btv->type].gpiomask2,~tvcards[btv->type].gpiomask2,
- BT848_GPIO_OUT_EN);
+ BT848_GPIO_OUT_EN);
/* This seems to get rid of some synchronization problems */
btand(~(3<<5), BT848_IFORM);
mdelay(10);
-
- input %= tvcards[btv->type].video_inputs;
+
+
+ input %= tvcards[btv->type].video_inputs;
if (input==tvcards[btv->type].svhs)
{
btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
@@ -638,13 +724,83 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input)
~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA);
}
+/*
+ * Set the registers for the size we have specified. Don't bother
+ * trying to understand this without the BT848 manual in front of
+ * you [AC].
+ *
+ * PS: The manual is free for download in .pdf format from
+ * www.brooktree.com - nicely done those folks.
+ */
+
+struct tvnorm
+{
+ u32 Fsc;
+ u16 swidth, sheight; /* scaled standard width, height */
+ u16 totalwidth;
+ u8 adelay, bdelay, iform;
+ u32 scaledtwidth;
+ u16 hdelayx1, hactivex1;
+ u16 vdelay;
+ u8 vbipack;
+};
-#define VBIBUF_SIZE 65536
-
-/* Maximum sample number per VBI line is 2044, NTSC delivers 1600
- Note that we write 2048-aligned to keep alignment to memory pages
- VBI_RISC is written so that it applies to either 2044 or 1600
+static struct tvnorm tvnorms[] = {
+ /* PAL-BDGHI */
+ /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+ /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
+#ifdef VIDEODAT
+ { 35468950,
+ 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ 1135, 186, 924, 0x20, 255},
+#else
+ { 35468950,
+ 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ 1135, 186, 924, 0x20, 255},
+#endif
+/*
+ { 35468950,
+ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+ 944, 186, 922, 0x20, 255},
*/
+ /* NTSC */
+ { 28636363,
+ 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+ 910, 128, 910, 0x1a, 144},
+/*
+ { 28636363,
+ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+ 780, 122, 754, 0x1a, 144},
+*/
+#if 0
+ /* SECAM EAST */
+ { 35468950,
+ 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+ 944, 186, 922, 0x20, 255},
+#else
+ /* SECAM L */
+ { 35468950,
+ 924, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
+ 1135, 186, 922, 0x20, 255},
+#endif
+ /* PAL-NC */
+ { 28636363,
+ 640, 576, 910, 0x68, 0x5d, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
+ 780, 130, 734, 0x1a, 144},
+ /* PAL-M */
+ { 28636363,
+ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+ 780, 135, 754, 0x1a, 144},
+ /* PAL-N */
+ { 35468950,
+ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
+ 944, 186, 922, 0x20, 144},
+ /* NTSC-Japan */
+ { 28636363,
+ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
+ 780, 135, 754, 0x16, 144},
+};
+#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
#define VBI_SPL 2044
/* RISC command to write one VBI data line */
@@ -660,7 +816,7 @@ static void make_vbitab(struct bttv *btv)
DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even));
DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));
DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));
-
+
*(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0;
for (i=0; i<16; i++)
{
@@ -696,12 +852,14 @@ int palette2fmt[] = {
BT848_COLOR_FMT_RGB15,
BT848_COLOR_FMT_YUY2,
BT848_COLOR_FMT_BtYUV,
- 0,
- 0,
- 0,
+ -1,
+ -1,
+ -1,
BT848_COLOR_FMT_RAW,
BT848_COLOR_FMT_YCrCb422,
BT848_COLOR_FMT_YCrCb411,
+ BT848_COLOR_FMT_YCrCb422,
+ BT848_COLOR_FMT_YCrCb411,
};
#define PALETTEFMT_MAX (sizeof(palette2fmt)/sizeof(int))
@@ -737,11 +895,120 @@ static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
}
-static int make_vrisctab(struct bttv *btv, unsigned int *ro,
+static int make_prisctab(struct bttv *btv, unsigned int *ro,
unsigned int *re,
unsigned int *vbuf, unsigned short width,
unsigned short height, unsigned short fmt)
{
+ unsigned long line, lmask;
+ unsigned long bl, blcr, blcb, rcmd;
+ unsigned long todo;
+ unsigned int **rp;
+ int inter;
+ unsigned long cbadr, cradr;
+ unsigned long vadr=(unsigned long) vbuf;
+ int shift, csize;
+
+
+ switch(fmt)
+ {
+ case VIDEO_PALETTE_YUV422P:
+ csize=(width*height)>>1;
+ shift=1;
+ lmask=0;
+ break;
+
+ case VIDEO_PALETTE_YUV411P:
+ csize=(width*height)>>2;
+ shift=2;
+ lmask=0;
+ break;
+
+ case VIDEO_PALETTE_YUV420P:
+ csize=(width*height)>>2;
+ shift=1;
+ lmask=1;
+ break;
+
+ case VIDEO_PALETTE_YUV410P:
+ csize=(width*height)>>4;
+ shift=2;
+ lmask=3;
+ break;
+
+ default:
+ return -1;
+ }
+ cbadr=vadr+(width*height);
+ cradr=cbadr+csize;
+ inter = (height>btv->win.cropheight/2) ? 1 : 0;
+
+ *(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(ro++)=0;
+ *(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(re++)=0;
+
+ for (line=0; line < (height<<(1^inter)); line++)
+ {
+ if(line==height)
+ {
+ vadr+=csize<<1;
+ cbadr=vadr+(width*height);
+ cradr=cbadr+csize;
+ }
+ if (inter)
+ rp= (line&1) ? &re : &ro;
+ else
+ rp= (line>=height) ? &re : &ro;
+
+
+ if(line&lmask)
+ rcmd=BT848_RISC_WRITE1S23|BT848_RISC_SOL;
+ else
+ rcmd=BT848_RISC_WRITE123|BT848_RISC_SOL;
+
+ todo=width;
+ while(todo)
+ {
+ bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
+ blcr=(PAGE_SIZE-((PAGE_SIZE-1)&cradr))<<shift;
+ blcb=(PAGE_SIZE-((PAGE_SIZE-1)&cbadr))<<shift;
+ bl=(blcr<bl) ? blcr : bl;
+ bl=(blcb<bl) ? blcb : bl;
+ bl=(bl>todo) ? todo : bl;
+ blcr=bl>>shift;
+ blcb=blcr;
+ /* bl now containts the longest row that can be written */
+ todo-=bl;
+ if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */
+
+ *((*rp)++)=rcmd|bl;
+ *((*rp)++)=blcb|(blcr<<16);
+ *((*rp)++)=kvirt_to_bus(vadr);
+ vadr+=bl;
+ if((rcmd&(15<<28))==BT848_RISC_WRITE123)
+ {
+ *((*rp)++)=kvirt_to_bus(cbadr);
+ cbadr+=blcb;
+ *((*rp)++)=kvirt_to_bus(cradr);
+ cradr+=blcr;
+ }
+
+ rcmd&=~BT848_RISC_SOL; /* only the first has SOL */
+ }
+ }
+
+ *(ro++)=BT848_RISC_JUMP;
+ *(ro++)=btv->bus_vbi_even;
+ *(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
+ *(re++)=btv->bus_vbi_odd;
+
+ return 0;
+}
+
+static int make_vrisctab(struct bttv *btv, unsigned int *ro,
+ unsigned int *re,
+ unsigned int *vbuf, unsigned short width,
+ unsigned short height, unsigned short palette)
+{
unsigned long line;
unsigned long bpl; /* bytes per line */
unsigned long bl;
@@ -750,11 +1017,14 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro,
int inter;
unsigned long vadr=(unsigned long) vbuf;
- if (btv->gfmt==BT848_COLOR_FMT_RAW)
+ if (palette==VIDEO_PALETTE_RAW)
return make_rawrisctab(btv, ro, re, vbuf);
+ if (palette>=VIDEO_PALETTE_PLANAR)
+ return make_prisctab(btv, ro, re, vbuf, width, height, palette);
+
inter = (height>btv->win.cropheight/2) ? 1 : 0;
- bpl=width*fmtbppx2[fmt&0xf]/2;
+ bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;
*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
@@ -764,7 +1034,7 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro,
if (inter)
rp= (line&1) ? &re : &ro;
else
- rp= (line>height) ? &re : &ro;
+ rp= (line>=height) ? &re : &ro;
bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
if (bpl<=bl)
@@ -802,16 +1072,62 @@ static int make_vrisctab(struct bttv *btv, unsigned int *ro,
return 0;
}
+static unsigned char lmaskt[8] =
+{ 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80};
+static unsigned char rmaskt[8] =
+{ 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+
static void clip_draw_rectangle(unsigned char *clipmap, int x, int y, int w, int h)
{
- int i, j;
+ unsigned char lmask, rmask, *p;
+ int W, l, r;
+ int i;
/* bitmap is fixed width, 128 bytes (1024 pixels represented) */
- if (x < 0 || y < 0 || w < 0 || h < 0) /* catch bad clips */
+ if (x<0)
+ {
+ w+=x;
+ x=0;
+ }
+ if (y<0)
+ {
+ h+=y;
+ y=0;
+ }
+ if (w < 0 || h < 0) /* catch bad clips */
return;
/* out of range data should just fall through */
- for (i = y; i < y + h && i < 625; i++)
- for (j = x; j < x + w && j < 1024; j++)
- clipmap[(i<<7)+(j>>3)] |= (1<<(j&7));
+ if (y+h>=625)
+ h=625-y;
+ if (x+w>=1024)
+ w=1024-x;
+
+ l=x>>3;
+ r=(x+w)>>3;
+ W=r-l-1;
+ lmask=lmaskt[x&7];
+ rmask=rmaskt[(x+w)&7];
+ p=clipmap+128*y+l;
+
+ if (W>0)
+ {
+ for (i=0; i<h; i++, p+=128)
+ {
+ *p|=lmask;
+ memset(p+1, 0xff, W);
+ p[W+1]|=rmask;
+ }
+ } else if (!W) {
+ for (i=0; i<h; i++, p+=128)
+ {
+ p[0]|=lmask;
+ p[1]|=rmask;
+ }
+ } else {
+ for (i=0; i<h; i++, p+=128)
+ p[0]|=lmask&rmask;
+ }
+
+
}
static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
@@ -903,73 +1219,6 @@ static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
*(re++)=btv->bus_vbi_odd;
}
-
-/*
- * Set the registers for the size we have specified. Don't bother
- * trying to understand this without the BT848 manual in front of
- * you [AC].
- *
- * PS: The manual is free for download in .pdf format from
- * www.brooktree.com - nicely done those folks.
- */
-
-struct tvnorm
-{
- u32 Fsc;
- u16 swidth, sheight; /* scaled standard width, height */
- u16 totalwidth;
- u8 adelay, bdelay, iform;
- u32 scaledtwidth;
- u16 hdelayx1, hactivex1;
- u16 vdelay;
- u8 vbipack;
-};
-
-static struct tvnorm tvnorms[] = {
- /* PAL-BDGHI */
- /* max pal/secam is actually 922, but 924 is divisible by 4 and 3! */
- /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */
- { 35468950,
- 924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 1135, 178, 924, 0x20, 255},
-/*
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
- 944, 178, 922, 0x20, 255},
-*/
- /* NTSC */
- { 28636363,
- 768, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
- 910, 128, 754, 0x1a, 144},
-/*
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
-*/
- /* SECAM - phase means nothing in SECAM, bdelay is useless */
- { 35468950,
- 924, 576,1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
- 1135, 178, 924, 0x20, 255},
- /* PAL-M */
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
- /* PAL-N */
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
- 944, 178, 922, 0x20, 255},
- /* PAL-NC */
- { 35468950,
- 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
- 944, 178, 922, 0x20, 255},
- /* NTSC-Japan */
- { 28636363,
- 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
- 780, 122, 754, 0x1a, 144},
-};
-#define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
-
-
/* set geometry for even/odd frames
just if you are wondering:
handling of even and odd frames will be separated, e.g. for grabbing
@@ -1030,10 +1279,11 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt)
btwrite(tvn->adelay, BT848_ADELAY);
btwrite(tvn->bdelay, BT848_BDELAY);
btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
- btwrite(1, BT848_VBI_PACK_DEL);
btwrite(tvn->vbipack, BT848_VBI_PACK_SIZE);
-
- set_pll(btv);
+ btwrite(1, BT848_VBI_PACK_DEL);
+
+ btv->pll.pll_ofreq = tvn->Fsc;
+ set_pll(btv);
btwrite(fmt, BT848_COLOR_FMT);
hactive=width;
@@ -1064,7 +1314,6 @@ static void bt848_set_geo(struct bttv *btv, u16 width, u16 height, u16 fmt)
hdelay, vdelay, crop);
bt848_set_eogeo(btv, 1, vtc, hscale, vscale, hactive, vactive,
hdelay, vdelay, crop);
-
}
@@ -1104,35 +1353,34 @@ static void set_freq(struct bttv *btv, unsigned short freq)
{
int fixme = freq; /* XXX */
- if (btv->radio)
- {
- if (btv->have_tuner)
+ /* mute */
+ if (btv->have_msp3400)
+ i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+ MSP_SWITCH_MUTE,0);
+
+ /* switch channel */
+ if (btv->have_tuner) {
+ if (btv->radio) {
i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
TUNER_SET_RADIOFREQ,&fixme);
-
- if (btv->have_msp3400) {
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_SET_RADIO,0);
- i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
- MSP_NEWCHANNEL,0);
- }
- }
- else
- {
- if (btv->have_tuner)
+ } else {
i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
TUNER_SET_TVFREQ,&fixme);
+ }
+ }
- if (btv->have_msp3400) {
+ if (btv->have_msp3400) {
+ if (btv->radio) {
+ i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
+ MSP_SET_RADIO,0);
+ } else {
i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
MSP_SET_TVNORM,&(btv->win.norm));
i2c_control_device(&(btv->i2c),I2C_DRIVERID_MSP3400,
MSP_NEWCHANNEL,0);
- }
- }
-
+ }
+ }
}
-
/*
* Grab into virtual memory.
@@ -1171,12 +1419,12 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
*/
if (mp->format >= PALETTEFMT_MAX)
return -EINVAL;
- if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
- > BTTV_MAX_FBUF)
+ if (mp->height*mp->width*fmtbppx2[palette2fmt[mp->format]&0x0f]/2
+ > BTTV_MAX_FBUF)
return -EINVAL;
- if (!palette2fmt[mp->format])
+ if(-1 == palette2fmt[mp->format])
return -EINVAL;
-
+
/*
* FIXME: Check the format of the grab here. This is probably
* also less restrictive than the normal overlay grabs. Stuff
@@ -1192,7 +1440,7 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
return -EAGAIN;*/
ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
re=ro+2048;
- make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, palette2fmt[mp->format]);
+ make_vrisctab(btv, ro, re, vbuf, mp->width, mp->height, mp->format);
/* bt848_set_risc_jmps(btv); */
btv->frame_stat[mp->frame] = GBUFFER_GRABBING;
if (btv->grabbing) {
@@ -1210,8 +1458,13 @@ static int vgrab(struct bttv *btv, struct video_mmap *mp)
btv->gre=virt_to_bus(re);
btv->grf=mp->frame;
}
- if (!(btv->grabbing++))
+ if (!(btv->grabbing++)) {
+ if(mp->format>=VIDEO_PALETTE_COMPONENT) {
+ btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
+ btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
+ }
btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
+ }
btor(3, BT848_CAP_CTL);
btor(3, BT848_GPIO_DMA_CTL);
/* interruptible_sleep_on(&btv->capq); */
@@ -1227,7 +1480,7 @@ static long bttv_read(struct video_device *v, char *buf, unsigned long count, in
{
struct bttv *btv= (struct bttv *)v;
int q,todo;
-
+ /* BROKEN: RETURNS VBI WHEN IT SHOULD RETURN GRABBED VIDEO FRAME */
todo=count;
while (todo && todo>(q=VBIBUF_SIZE-btv->vbip))
{
@@ -1275,36 +1528,27 @@ static int bttv_open(struct video_device *dev, int flags)
struct bttv *btv = (struct bttv *)dev;
int users, i;
- switch (flags)
- {
- case 0:
- if (btv->user)
- return -EBUSY;
- btv->user++;
- audio(btv, AUDIO_UNMUTE);
- for (i=users=0; i<bttv_num; i++)
- users+=bttvs[i].user;
- if (users==1)
- find_vga();
- btv->fbuffer=NULL;
- if (!btv->fbuffer)
- btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
- if (!btv->fbuffer)
- {
- btv->user--;
- return -EINVAL;
- }
- btv->grabbing = 0;
- btv->grab = 0;
- btv->lastgrab = 0;
- for (i = 0; i < MAX_GBUFFERS; i++)
- btv->frame_stat[i] = GBUFFER_UNUSED;
- break;
- case 1:
- break;
- }
- MOD_INC_USE_COUNT;
- return 0;
+ if (btv->user)
+ return -EBUSY;
+ audio(btv, AUDIO_UNMUTE);
+ for (i=users=0; i<bttv_num; i++)
+ users+=bttvs[i].user;
+ if (users==1)
+ find_vga();
+ btv->fbuffer=NULL;
+ if (!btv->fbuffer)
+ btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
+ if (!btv->fbuffer)
+ return -EINVAL;
+ btv->grabbing = 0;
+ btv->grab = 0;
+ btv->lastgrab = 0;
+ for (i = 0; i < MAX_GBUFFERS; i++)
+ btv->frame_stat[i] = GBUFFER_UNUSED;
+
+ btv->user++;
+ MOD_INC_USE_COUNT;
+ return 0;
}
static void bttv_close(struct video_device *dev)
@@ -1393,8 +1637,8 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
VID_TYPE_SCALES;
b.channels = tvcards[btv->type].video_inputs;
b.audios = tvcards[btv->type].audio_inputs;
- b.maxwidth = 768;
- b.maxheight = 576;
+ b.maxwidth = tvnorms[btv->win.norm].swidth;
+ b.maxheight = tvnorms[btv->win.norm].sheight;
b.minwidth = 32;
b.minheight = 32;
if(copy_to_user(arg,&b,sizeof(b)))
@@ -1420,7 +1664,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.tuners=1;
}
else if(v.channel==tvcards[btv->type].svhs)
- strcpy(v.name,"SVHS");
+ strcpy(v.name,"S-Video");
else
sprintf(v.name,"Composite%d",v.channel);
@@ -1437,14 +1681,14 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
- if (v.channel>=tvcards[btv->type].video_inputs)
+ if (v.channel>tvcards[btv->type].video_inputs)
return -EINVAL;
bt848_muxsel(btv, v.channel);
if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
&&v.norm!=VIDEO_MODE_SECAM)
return -EOPNOTSUPP;
btv->win.norm = v.norm;
- make_vbitab(btv);
+ make_vbitab(btv);
bt848_set_winsize(btv);
btv->channel=v.channel;
return 0;
@@ -1460,6 +1704,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.rangelow=0;
v.rangehigh=0xFFFFFFFF;
v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
+ if (btv->audio_chip == TDA9840) {
+ v.flags |= VIDEO_AUDIO_VOLUME;
+ v.mode = VIDEO_SOUND_MONO|VIDEO_SOUND_STEREO;
+ v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2;
+ }
+ if (btv->audio_chip == TDA9850) {
+ unsigned char ALR1;
+ ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
+ if (ALR1 & 32)
+ v.flags |= VIDEO_TUNER_STEREO_ON;
+ }
v.mode = btv->win.norm;
v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
if(copy_to_user(arg,&v,sizeof(v)))
@@ -1472,7 +1727,6 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
struct video_tuner v;
if(copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
-
/* Only one channel has a tuner */
if(v.tuner!=tvcards[btv->type].tuner)
return -EINVAL;
@@ -1536,13 +1790,17 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(copy_from_user(&vw,arg,sizeof(vw)))
return -EFAULT;
- if(vw.flags || vw.width < 16 || vw.height < 16) {
- bt848_cap(btv,0);
+ if(vw.flags || vw.width < 16 || vw.height < 16)
+ {
+ bt848_cap(btv,0);
return -EINVAL;
- }
- if (btv->win.bpp < 4) { /* adjust and align writes */
+ }
+ if (btv->win.bpp < 4)
+ { /* 32-bit align start and adjust width */
+ int i = vw.x;
vw.x = (vw.x + 3) & ~3;
- vw.width = (vw.width - 3) & ~3;
+ i = vw.x - i;
+ vw.width -= i;
}
btv->win.x=vw.x;
btv->win.y=vw.y;
@@ -1584,7 +1842,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
make_clip_tab(btv, vcp, vw.clipcount);
if (vw.clipcount != 0)
vfree(vcp);
- if(on && btv->win.vidadr != 0)
+ if(on && btv->win.vidadr!=0)
bt848_cap(btv,1);
return 0;
}
@@ -1638,7 +1896,11 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCSFBUF:
{
struct video_buffer v;
+#if LINUX_VERSION_CODE >= 0x020100
if(!capable(CAP_SYS_ADMIN))
+#else
+ if(!suser())
+#endif
return -EPERM;
if(copy_from_user(&v, arg,sizeof(v)))
return -EFAULT;
@@ -1646,7 +1908,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.depth!=24 && v.depth!=32 && v.width > 16 &&
v.height > 16 && v.bytesperline > 16)
return -EINVAL;
- btv->win.vidadr=(unsigned long)v.base;
+ if (v.base)
+ {
+ if ((unsigned long)v.base&1)
+ btv->win.vidadr=(unsigned long)(PAGE_OFFSET|uvirt_to_bus((unsigned long)v.base));
+ else
+ btv->win.vidadr=(unsigned long)v.base;
+ }
btv->win.sheight=v.height;
btv->win.swidth=v.width;
btv->win.bpp=((v.depth+7)&0x38)/8;
@@ -1687,6 +1955,13 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE);
v.flags|=VIDEO_AUDIO_MUTABLE;
strcpy(v.name,"TV");
+ if (btv->audio_chip == TDA9850) {
+ unsigned char ALR1;
+ ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
+ v.mode = VIDEO_SOUND_MONO;
+ v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0;
+ v.mode |= (ALR1 & 64) ? VIDEO_SOUND_LANG1:0;
+ }
if (btv->have_msp3400)
{
v.flags|=VIDEO_AUDIO_VOLUME |
@@ -1719,13 +1994,21 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
audio(btv, AUDIO_MUTE);
/* One audio source per tuner */
/* if(v.audio!=0) */
- /* Nope... I have three on my ADSTech TV card. The*/
- /* ADSTech TV+FM prolly has 4 <rriggs@tesser.com> */
- if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
+ /* ADSTech TV card has more than one */
+ if(v.audio<0 || v.audio >= tvcards[btv->type].audio_inputs)
return -EINVAL;
bt848_muxsel(btv,v.audio);
if(!(v.flags&VIDEO_AUDIO_MUTE))
audio(btv, AUDIO_UNMUTE);
+ if (btv->audio_chip == TDA9850) {
+ unsigned char con3 = 0;
+ if (v.mode & VIDEO_SOUND_LANG1)
+ con3 = 0x80; /* sap */
+ if (v.mode & VIDEO_SOUND_STEREO)
+ con3 = 0x40; /* stereo */
+ I2CWrite(&(btv->i2c), I2C_TDA9850,
+ TDA9850_CON3, con3, 1);
+ }
if (btv->have_msp3400)
{
i2c_control_device(&(btv->i2c),
@@ -1748,13 +2031,18 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCSYNC:
if(copy_from_user((void *)&i,arg,sizeof(int)))
return -EFAULT;
- if (i>1 || i<0)
- return -EINVAL;
+/* if(i>1 || i<0)
+ return -EINVAL;
+*/
switch (btv->frame_stat[i]) {
case GBUFFER_UNUSED:
return -EINVAL;
case GBUFFER_GRABBING:
- interruptible_sleep_on(&btv->capq);
+ while(btv->frame_stat[i]==GBUFFER_GRABBING) {
+ interruptible_sleep_on(&btv->capq);
+ if(signal_pending(current))
+ return -EINTR;
+ }
/* fall */
case GBUFFER_DONE:
btv->frame_stat[i] = GBUFFER_UNUSED;
@@ -1763,7 +2051,11 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return 0;
case BTTV_WRITEE:
+#if LINUX_VERSION_CODE >= 0x020100
if(!capable(CAP_SYS_ADMIN))
+#else
+ if(!suser())
+#endif
return -EPERM;
if(copy_from_user((void *) eedata, (void *) arg, 256))
return -EFAULT;
@@ -1771,32 +2063,39 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return 0;
case BTTV_READEE:
+#if LINUX_VERSION_CODE >= 0x020100
if(!capable(CAP_SYS_ADMIN))
+#else
+ if(!suser())
+#endif
return -EPERM;
readee(&(btv->i2c), eedata);
if(copy_to_user((void *) arg, (void *) eedata, 256))
return -EFAULT;
break;
- case BTTV_FIELDNR:
+ case BTTV_FIELDNR:
if(copy_to_user((void *) arg, (void *) &btv->last_field,
sizeof(btv->last_field)))
return -EFAULT;
break;
-
- case BTTV_PLLSET:
- {
- struct bttv_pll_info p;
+
+ case BTTV_PLLSET: {
+ struct bttv_pll_info p;
+#if LINUX_VERSION_CODE >= 0x020100
if(!capable(CAP_SYS_ADMIN))
- return -EPERM;
- if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
+#else
+ if(!suser())
+#endif
+ return -EPERM;
+ if(copy_from_user(&p , (void *) arg, sizeof(btv->pll)))
return -EFAULT;
- btv->pll.pll_ifreq = p.pll_ifreq;
- btv->pll.pll_ofreq = p.pll_ofreq;
- btv->pll.pll_crystal = p.pll_crystal;
- break;
- }
+ btv->pll.pll_ifreq = p.pll_ifreq;
+ btv->pll.pll_ofreq = p.pll_ofreq;
+ btv->pll.pll_crystal = p.pll_crystal;
+ break;
+ }
case VIDIOCMCAPTURE:
{
struct video_mmap vm;
@@ -1840,7 +2139,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EFAULT;
return 0;
}
-
+
case BTTV_BURST_ON:
{
tvnorms[0].scaledtwidth=1135-BURSTOFFSET-2;
@@ -1855,9 +2154,14 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return 0;
}
+ case BTTV_VERSION:
+ {
+ return BTTV_VERSION_CODE;
+ }
+
case BTTV_PICNR:
{
- /* return picture */
+ /* return picture;*/
return 0;
}
@@ -1916,7 +2220,9 @@ static struct video_device bttv_template=
bttv_close,
bttv_read,
bttv_write,
+#if LINUX_VERSION_CODE >= 0x020100
NULL, /* poll */
+#endif
bttv_ioctl,
bttv_mmap,
bttv_init_done,
@@ -1970,6 +2276,7 @@ static long vbi_read(struct video_device *v, char *buf, unsigned long count,
return count;
}
+#if LINUX_VERSION_CODE >= 0x020100
static unsigned int vbi_poll(struct video_device *dev, struct file *file,
poll_table *wait)
{
@@ -1983,6 +2290,7 @@ static unsigned int vbi_poll(struct video_device *dev, struct file *file,
return mask;
}
+#endif
static int vbi_open(struct video_device *dev, int flags)
{
@@ -2021,7 +2329,9 @@ static struct video_device vbi_template=
vbi_close,
vbi_read,
bttv_write,
+#if LINUX_VERSION_CODE >= 0x020100
vbi_poll,
+#endif
vbi_ioctl,
NULL, /* no mmap yet */
bttv_init_done,
@@ -2131,7 +2441,9 @@ static struct video_device radio_template=
radio_close,
radio_read, /* just returns -EINVAL */
bttv_write, /* just returns -EINVAL */
+#if LINUX_VERSION_CODE >= 0x020100
NULL, /* no poll */
+#endif
radio_ioctl,
NULL, /* no mmap */
bttv_init_done, /* just returns 0 */
@@ -2149,14 +2461,14 @@ struct vidbases
};
static struct vidbases vbs[] = {
- { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,
- "Alliance AT3D", PCI_BASE_ADDRESS_0},
+ { PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D,
+ "Alliance AT3D", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222,
"ATI MACH64 CT", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,
"ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT,
- "ATI MACH64 GT", PCI_BASE_ADDRESS_0},
+ "ATI MACH64 GT", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_CIRRUS, 0, "Cirrus Logic", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA,
"DEC DC21030", PCI_BASE_ADDRESS_0},
@@ -2167,6 +2479,7 @@ static struct vidbases vbs[] = {
{ PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,
"Matrox Millennium II AGP", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
+ { PCI_VENDOR_ID_MATROX, 0x0521, "Matrox G200", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128,
"Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
{ PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128_2,
@@ -2192,6 +2505,8 @@ static uint dec_offsets[4] = {
/* Scan for PCI display adapter
if more than one card is present the last one is used for now */
+#if LINUX_VERSION_CODE >= 0x020100
+
static int find_vga(void)
{
unsigned short badr;
@@ -2271,6 +2586,99 @@ static int find_vga(void)
return found;
}
+#else
+static int find_vga(void)
+{
+ unsigned int devfn, class, vendev;
+ unsigned short vendor, device, badr;
+ int found=0, bus=0, i, tga_type;
+ unsigned int vidadr=0;
+
+
+ for (devfn = 0; devfn < 0xff; devfn++)
+ {
+ if (PCI_FUNC(devfn) != 0)
+ continue;
+ pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendev);
+ if (vendev == 0xffffffff || vendev == 0x00000000)
+ continue;
+ pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &device);
+ pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class);
+ class = class >> 16;
+/* if (class == PCI_CLASS_DISPLAY_VGA) {*/
+ if ((class>>8) == PCI_BASE_CLASS_DISPLAY ||
+ /* Number 9 GXE64Pro needs this */
+ class == PCI_CLASS_NOT_DEFINED_VGA)
+ {
+ badr=0;
+ printk(KERN_INFO "bttv: PCI display adapter: ");
+ for (i=0; i<NR_CARDS; i++)
+ {
+ if (vendor==vbs[i].vendor)
+ {
+ if (vbs[i].device)
+ if (vbs[i].device!=device)
+ continue;
+ printk("%s.\n", vbs[i].name);
+ badr=vbs[i].badr;
+ break;
+ }
+ }
+ if (NR_CARDS == i)
+ printk("UNKNOWN.\n");
+ if (!badr)
+ {
+ printk(KERN_ERR "bttv: Unknown video memory base address.\n");
+ continue;
+ }
+ pcibios_read_config_dword(bus, devfn, badr, &vidadr);
+ if (vidadr & PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ printk(KERN_ERR "bttv: Memory seems to be I/O memory.\n");
+ printk(KERN_ERR "bttv: Check entry for your card type in bttv.c vidbases struct.\n");
+ continue;
+ }
+ vidadr &= PCI_BASE_ADDRESS_MEM_MASK;
+ if (!vidadr)
+ {
+ printk(KERN_ERR "bttv: Memory @ 0, must be something wrong!\n");
+ continue;
+ }
+
+ if (vendor==PCI_VENDOR_ID_DEC)
+ if (device==PCI_DEVICE_ID_DEC_TGA)
+ {
+ tga_type = (readl((unsigned long)vidadr) >> 12) & 0x0f;
+ if (tga_type != 0 && tga_type != 1 && tga_type != 3)
+ {
+ printk(KERN_ERR "bttv: TGA type (0x%x) unrecognized!\n", tga_type);
+ found--;
+ }
+ vidadr+=dec_offsets[tga_type];
+ }
+
+ DEBUG(printk(KERN_DEBUG "bttv: memory @ 0x%08x, ", vidadr));
+ DEBUG(printk(KERN_DEBUG "devfn: 0x%04x.\n", devfn));
+ found++;
+ }
+ }
+
+ if (vidmem)
+ {
+ if (vidmem < 0x1000)
+ vidadr=vidmem<<20;
+ else
+ vidadr=vidmem;
+ printk(KERN_INFO "bttv: Video memory override: 0x%08x\n", vidadr);
+ found=1;
+ }
+ for (i=0; i<BTTV_MAX; i++)
+ bttvs[i].win.vidadr=vidadr;
+
+ return found;
+}
+#endif
#define TRITON_PCON 0x50
@@ -2279,6 +2687,9 @@ static int find_vga(void)
#define TRITON_WRITE_BURST (1<<2)
#define TRITON_PEER_CONCURRENCY (1<<3)
+
+#if LINUX_VERSION_CODE >= 0x020100
+
static void handle_chipset(void)
{
struct pci_dev *dev = NULL;
@@ -2342,6 +2753,78 @@ static void handle_chipset(void)
#endif
}
}
+#else
+static void handle_chipset(void)
+{
+ int index;
+
+ for (index = 0; index < 8; index++)
+ {
+ unsigned char bus, devfn;
+ unsigned char b;
+
+ /* Beware the SiS 85C496 my friend - rev 49 don't work with a bttv */
+
+ if (!pcibios_find_device(PCI_VENDOR_ID_SI,
+ PCI_DEVICE_ID_SI_496,
+ index, &bus, &devfn))
+ {
+ printk(KERN_WARNING "BT848 and SIS 85C496 chipset don't always work together.\n");
+ }
+
+ if (!pcibios_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82441,
+ index, &bus, &devfn))
+ {
+ pcibios_read_config_byte(bus, devfn, 0x53, &b);
+ DEBUG(printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, "));
+ DEBUG(printk("bufcon=0x%02x\n",b));
+ }
+
+ if (!pcibios_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437,
+ index, &bus, &devfn))
+ {
+ printk(KERN_INFO "bttv: Host bridge 82437FX Triton PIIX\n");
+ triton1=BT848_INT_ETBF;
+
+#if 0
+ /* The ETBF bit SHOULD make all this unnecessary */
+ /* 430FX (Triton I) freezes with bus concurrency on -> switch it off */
+ {
+ unsigned char bo;
+
+ pcibios_read_config_byte(bus, devfn, TRITON_PCON, &b);
+ bo=b;
+ DEBUG(printk(KERN_DEBUG "bttv: 82437FX: PCON: 0x%x\n",b));
+
+ if(!(b & TRITON_BUS_CONCURRENCY))
+ {
+ printk(KERN_WARNING "bttv: 82437FX: disabling bus concurrency\n");
+ b |= TRITON_BUS_CONCURRENCY;
+ }
+
+ if(b & TRITON_PEER_CONCURRENCY)
+ {
+ printk(KERN_WARNING "bttv: 82437FX: disabling peer concurrency\n");
+ b &= ~TRITON_PEER_CONCURRENCY;
+ }
+ if(!(b & TRITON_STREAMING))
+ {
+ printk(KERN_WARNING "bttv: 82437FX: disabling streaming\n");
+ b |= TRITON_STREAMING;
+ }
+
+ if (b!=bo)
+ {
+ pcibios_write_config_byte(bus, devfn, TRITON_PCON, b);
+ printk(KERN_DEBUG "bttv: 82437FX: PCON changed to: 0x%x\n",b);
+ }
+ }
+#endif
+ }
+ }
+}
+#endif
static void init_tda8425(struct i2c_bus *bus)
{
@@ -2349,9 +2832,13 @@ static void init_tda8425(struct i2c_bus *bus)
I2CWrite(bus, I2C_TDA8425, TDA8425_VR, 0xFC, 1); /* volume right 0dB */
I2CWrite(bus, I2C_TDA8425, TDA8425_BA, 0xF6, 1); /* bass 0dB */
I2CWrite(bus, I2C_TDA8425, TDA8425_TR, 0xF6, 1); /* treble 0dB */
- I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
+ I2CWrite(bus, I2C_TDA8425, TDA8425_S1, 0xCE, 1); /* mute off */
}
+static void init_tda9840(struct i2c_bus *bus)
+{
+ I2CWrite(bus, I2C_TDA9840, TDA9840_SW, 0x2A, 1); /* Sound mode switching */
+}
static void init_tda9850(struct i2c_bus *bus)
{
@@ -2372,7 +2859,6 @@ static void idcard(int i)
{
struct bttv *btv = &bttvs[i];
- int tunertype;
btwrite(0, BT848_GPIO_OUT_EN);
DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA)));
@@ -2385,95 +2871,123 @@ static void idcard(int i)
*/
if (btv->type == BTTV_UNKNOWN)
{
- btv->type=BTTV_MIRO;
-
- if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) {
+ if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0)
+ {
if(btv->id>849)
btv->type=BTTV_HAUPPAUGE878;
else
- btv->type=BTTV_HAUPPAUGE;
+ btv->type=BTTV_HAUPPAUGE;
+
+ } else if (I2CRead(&(btv->i2c), I2C_STBEE)>=0) {
+ btv->type=BTTV_STB;
+ } else
+ if (I2CRead(&(btv->i2c), I2C_VHX)>=0) {
+ btv->type=BTTV_VHX;
+ } else {
+ if (I2CRead(&(btv->i2c), 0x80)>=0) /* check for msp34xx */
+ btv->type = BTTV_MIROPRO;
+ else
+ btv->type=BTTV_MIRO;
}
- else
- if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
- btv->type=BTTV_STB;
-
- if (btv->type == BTTV_MIRO) {
- /* auto detect tuner for MIRO cards */
- btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
- }
}
+ /* board specific initialisations */
+ if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
+ /* auto detect tuner for MIRO cards */
+ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+ }
+ if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
+ hauppauge_msp_reset(btv);
+ hauppauge_eeprom(&(btv->i2c));
+ if (btv->type == BTTV_HAUPPAUGE878) {
+ /* all bt878 hauppauge boards use this ... */
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ }
+ }
+ if(btv->type==BTTV_AVERMEDIA98)
+ {
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ }
+
+ if (btv->have_tuner && btv->tuner_type != -1)
+ i2c_control_device(&(btv->i2c),
+ I2C_DRIVERID_TUNER,
+ TUNER_SET_TYPE,&btv->tuner_type);
+
+
+ if (I2CRead(&(btv->i2c), I2C_TDA9840) >=0)
+ {
+ btv->audio_chip = TDA9840;
+ printk(KERN_INFO "bttv%d: audio chip: TDA9840\n", btv->nr);
+ }
+
if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0)
{
- btv->audio_chip = TDA9850;
- printk(KERN_INFO "bttv%d: audio chip: TDA9850\n", i);
+ btv->audio_chip = TDA9850;
+ printk(KERN_INFO "bttv%d: audio chip: TDA9850\n",btv->nr);
}
if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0)
{
- btv->audio_chip = TDA8425;
- printk("bttv%d: audio chip: TDA8425\n", i);
+ btv->audio_chip = TDA8425;
+ printk(KERN_INFO "bttv%d: audio chip: TDA8425\n",btv->nr);
}
switch(btv->audio_chip)
{
case TDA9850:
init_tda9850(&(btv->i2c));
- break;
- case TDA8425:
+ break;
+ case TDA9840:
+ init_tda9840(&(btv->i2c));
+ break;
+ case TDA8425:
init_tda8425(&(btv->i2c));
break;
}
+
+ printk(KERN_INFO "bttv%d: model: ",btv->nr);
- /* How do I detect the tuner type for other cards but Miro ??? */
- printk(KERN_INFO "bttv%d: model: ", btv->nr);
sprintf(btv->video_dev.name,"BT%d",btv->id);
switch (btv->type)
{
- case BTTV_MIRO:
- case BTTV_MIROPRO:
- printk("MIRO\n");
- if (btv->have_tuner)
- {
- tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
- i2c_control_device(&(btv->i2c),
- I2C_DRIVERID_TUNER,
- TUNER_SET_TYPE,&tunertype);
- }
- strcat(btv->video_dev.name,"(Miro)");
+ case BTTV_MIRO:
+ case BTTV_MIROPRO:
+ strcat(btv->video_dev.name,
+ (btv->type == BTTV_MIRO) ? "(Miro)" : "(Miro pro)");
break;
case BTTV_HAUPPAUGE:
+ strcat(btv->video_dev.name,"(Hauppauge old)");
+ break;
case BTTV_HAUPPAUGE878:
- printk("HAUPPAUGE\n");
- strcat(btv->video_dev.name,"(Hauppauge)");
+ strcat(btv->video_dev.name,"(Hauppauge new)");
break;
case BTTV_STB:
- printk("STB\n");
strcat(btv->video_dev.name,"(STB)");
break;
case BTTV_INTEL:
- printk("Intel\n");
strcat(btv->video_dev.name,"(Intel)");
break;
case BTTV_DIAMOND:
- printk("Diamond\n");
strcat(btv->video_dev.name,"(Diamond)");
break;
case BTTV_AVERMEDIA:
- printk("AVerMedia\n");
strcat(btv->video_dev.name,"(AVerMedia)");
break;
case BTTV_MATRIX_VISION:
- printk("MATRIX-Vision\n");
strcat(btv->video_dev.name,"(MATRIX-Vision)");
break;
- case BTTV_ADSTECH_TV:
- printk("ADSTech Channel Surfer TV\n");
- strcat(btv->video_dev.name,"(ADSTech Channel Surfer TV)");
- btv->tuner_type=8;
+ case BTTV_AVERMEDIA98:
+ strcat(btv->video_dev.name,"(AVerMedia TVCapture 98)");
break;
+ case BTTV_VHX:
+ strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)");
+ break;
}
- audio(btv, AUDIO_INTERN);
+ printk("%s\n",btv->video_dev.name);
+ audio(btv, AUDIO_MUTE);
}
@@ -2522,7 +3036,7 @@ static void bt848_set_risc_jmps(struct bttv *btv)
btv->risc_jmp[12]=BT848_RISC_JUMP;
btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
- /* enable capturing and DMA */
+ /* enable cpaturing and DMA */
btaor(flags, ~0x0f, BT848_CAP_CTL);
if (flags&0x0f)
bt848_dma(btv, 3);
@@ -2530,7 +3044,6 @@ static void bt848_set_risc_jmps(struct bttv *btv)
bt848_dma(btv, 0);
}
-
static int init_bt848(int i)
{
struct bttv *btv = &bttvs[i];
@@ -2541,19 +3054,7 @@ static int init_bt848(int i)
btwrite(0, BT848_SRESET);
DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem));
-#ifdef RESET_MSP_HAUPPAUGE
- /* Reset the MSP on some Hauppauge cards */
- /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */
- /* Can this hurt cards without one? What about Miros with MSP? */
- btaor(32, ~32, BT848_GPIO_OUT_EN);
- btaor(0, ~32, BT848_GPIO_DATA);
- udelay(2500);
- btaor(32, ~32, BT848_GPIO_DATA);
- btaor(0, ~32, BT848_GPIO_OUT_EN);
-#endif
-
/* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
-
btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */
btv->win.interlace=1;
btv->win.x=0;
@@ -2582,7 +3083,10 @@ static int init_bt848(int i)
btv->grabcount=0;
btv->grab=0;
btv->lastgrab=0;
- btv->field=btv->last_field=0;
+ btv->field=btv->last_field=0;
+ /* cevans - prevents panic if initialization bails due to memory
+ * alloc failures!
+ */
btv->video_dev.minor = -1;
btv->vbi_dev.minor = -1;
btv->radio_dev.minor = -1;
@@ -2613,6 +3117,7 @@ static int init_bt848(int i)
memset(btv->vbibuf, 0, VBIBUF_SIZE); /* We don't want to return random
memory to the user */
+
btv->fbuffer=NULL;
bt848_muxsel(btv, 1);
@@ -2621,7 +3126,7 @@ static int init_bt848(int i)
/* btwrite(0, BT848_TDEC); */
btwrite(0x10, BT848_COLOR_CTL);
btwrite(0x00, BT848_CAP_CTL);
- btwrite(0xfc, BT848_GPIO_DMA_CTL);
+ btwrite(0xac, BT848_GPIO_DMA_CTL);
/* select direct input */
btwrite(0x00, BT848_GPIO_REG_INP);
@@ -2671,6 +3176,7 @@ static int init_bt848(int i)
memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
+
idcard(i);
if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
@@ -2730,7 +3236,7 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
if (astat&BT848_INT_VSYNC)
{
IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr));
- btv->field++;
+ btv->field++;
}
if (astat&BT848_INT_SCERR) {
IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
@@ -2756,8 +3262,9 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
/* captured full frame */
if (stat&(2<<28))
{
+ wake_up_interruptible(&btv->capq);
btv->last_field=btv->field;
- btv->grab++;
+ btv->grab++;
btv->frame_stat[btv->grf] = GBUFFER_DONE;
if ((--btv->grabbing))
{
@@ -2774,7 +3281,9 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
btv->gfmt);
} else {
bt848_set_risc_jmps(btv);
- bt848_set_geo(btv, btv->win.width,
+ btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
+ btand(~BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
+ bt848_set_geo(btv, btv->win.width,
btv->win.height,
btv->win.color_fmt);
}
@@ -2820,12 +3329,10 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
}
if (astat&BT848_INT_HLOCK)
{
-#if 0
if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio))
audio(btv, AUDIO_ON);
else
audio(btv, AUDIO_OFF);
-#endif
}
if (astat&BT848_INT_I2CDONE)
@@ -2834,7 +3341,8 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
count++;
if (count > 10)
- printk (KERN_WARNING "bttv%d: irq loop %d\n", btv->nr, count);
+ printk (KERN_WARNING "bttv%d: irq loop %d\n",
+ btv->nr,count);
if (count > 20)
{
btwrite(0, BT848_INT_MASK);
@@ -2850,17 +3358,16 @@ static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs)
* Scan for a Bt848 card, request the irq and map the io memory
*/
+#if LINUX_VERSION_CODE >= 0x020100
int configure_bt848(struct pci_dev *dev, int bttv_num)
{
int result;
- unsigned char bus, devfn, command;
+ unsigned char command;
struct bttv *btv;
btv=&bttvs[bttv_num];
btv->dev=dev;
btv->nr = bttv_num;
- btv->bus=bus=dev->bus->number;
- btv->devfn=devfn=dev->devfn;
btv->bt848_mem=NULL;
btv->vbibuf=NULL;
btv->risc_jmp=NULL;
@@ -2896,15 +3403,14 @@ int configure_bt848(struct pci_dev *dev, int bttv_num)
pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
bttv_num,btv->id, btv->revision);
- printk("bus: %d, devfn: %d, ",
- btv->bus, btv->devfn);
+ printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn);
printk("irq: %d, ",btv->irq);
printk("memory: 0x%08x.\n", btv->bt848_adr);
-
- btv->pll.pll_ifreq=0;
- btv->pll.pll_ofreq=0;
- btv->pll.pll_crystal=0;
- btv->pll.pll_current=0;
+
+ btv->pll.pll_crystal = 0;
+ btv->pll.pll_ifreq = 0;
+ btv->pll.pll_ofreq = 0;
+ btv->pll.pll_current = 0;
if (!(btv->id==848 && btv->revision==0x11)) {
switch (pll[btv->nr]) {
case 0:
@@ -2922,10 +3428,10 @@ int configure_bt848(struct pci_dev *dev, int bttv_num)
break;
}
}
-
+
btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
- /* clear interrupt mask */
+ /* clear interrupt mask */
btwrite(0, BT848_INT_MASK);
result = request_irq(btv->irq, bttv_irq,
@@ -2988,7 +3494,170 @@ static int find_bt848(void)
printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
return bttv_num;
}
-
+#else
+static int find_bt848(void)
+{
+ short pci_index;
+ unsigned char command, latency;
+ int result;
+ unsigned char bus, devfn;
+ struct bttv *btv;
+
+ bttv_num=0;
+
+ if (!pcibios_present())
+ {
+ DEBUG(printk(KERN_DEBUG "bttv%d: PCI-BIOS not present or not accessable!\n",bttv_num));
+ return 0;
+ }
+
+ for (pci_index = 0;
+ !pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
+ pci_index, &bus, &devfn)
+ ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
+ pci_index, &bus, &devfn)
+ ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
+ pci_index, &bus, &devfn)
+ ||!pcibios_find_device(PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
+ pci_index, &bus, &devfn);
+ ++pci_index)
+ {
+ btv=&bttvs[bttv_num];
+ btv->nr = bttv_num;
+ btv->bus=bus;
+ btv->devfn=devfn;
+ btv->bt848_mem=NULL;
+ btv->vbibuf=NULL;
+ btv->risc_jmp=NULL;
+ btv->vbi_odd=NULL;
+ btv->vbi_even=NULL;
+ btv->vbiq=NULL;
+ btv->capq=NULL;
+ btv->capqo=NULL;
+ btv->capqe=NULL;
+
+ btv->vbip=VBIBUF_SIZE;
+
+ pcibios_read_config_word(btv->bus, btv->devfn, PCI_DEVICE_ID,
+ &btv->id);
+ pcibios_read_config_byte(btv->bus, btv->devfn,
+ PCI_INTERRUPT_LINE, &btv->irq);
+ pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
+ &btv->bt848_adr);
+ if (btv->id >= 878)
+ btv->i2c_command = 0x83;
+ else
+ btv->i2c_command=
+ (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
+
+ if (remap[bttv_num])
+ {
+ if (remap[bttv_num] < 0x1000)
+ remap[bttv_num]<<=20;
+ remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK;
+ printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n",
+ bttv_num,remap[bttv_num]);
+ remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
+ pcibios_write_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
+ remap[bttv_num]);
+ pcibios_read_config_dword(btv->bus, btv->devfn, PCI_BASE_ADDRESS_0,
+ &btv->bt848_adr);
+ }
+
+ btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_CLASS_REVISION,
+ &btv->revision);
+ printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
+ bttv_num,btv->id, btv->revision);
+ printk("bus: %d, devfn: %d, ",
+ btv->bus, btv->devfn);
+ printk("irq: %d, ",btv->irq);
+ printk("memory: 0x%08x.\n", btv->bt848_adr);
+
+ btv->pll.pll_crystal = 0;
+ btv->pll.pll_ifreq = 0;
+ btv->pll.pll_ofreq = 0;
+ btv->pll.pll_current = 0;
+ if (!(btv->id==848 && btv->revision==0x11)) {
+ switch (pll[btv->nr]) {
+ case 0:
+ /* off */
+ break;
+ case 1:
+ /* 28 MHz crystal installed */
+ btv->pll.pll_ifreq=28636363;
+ btv->pll.pll_crystal=BT848_IFORM_XT0;
+ break;
+ case 2:
+ /* 35 MHz crystal installed */
+ btv->pll.pll_ifreq=35468950;
+ btv->pll.pll_crystal=BT848_IFORM_XT1;
+ break;
+ }
+ }
+
+ btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
+
+ result = request_irq(btv->irq, bttv_irq,
+ SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv);
+ if (result==-EINVAL)
+ {
+ printk(KERN_ERR "bttv%d: Bad irq number or handler\n",
+ bttv_num);
+ return -EINVAL;
+ }
+ if (result==-EBUSY)
+ {
+ printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq);
+ return result;
+ }
+ if (result < 0)
+ return result;
+
+ /* Enable bus-mastering */
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+ command|=PCI_COMMAND_MASTER;
+ pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+ if (!(command&PCI_COMMAND_MASTER))
+ {
+ printk(KERN_ERR "bttv%d: PCI bus-mastering could not be enabled\n",bttv_num);
+ return -1;
+ }
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_LATENCY_TIMER,
+ &latency);
+ if (!latency)
+ {
+ latency=32;
+ pcibios_write_config_byte(btv->bus, btv->devfn,
+ PCI_LATENCY_TIMER, latency);
+ }
+ DEBUG(printk(KERN_DEBUG "bttv%d: latency: %02x\n",
+ bttv_num, latency));
+
+ btv->triton1=triton1 ? BT848_INT_ETBF : 0;
+ if (triton1 && btv->id >= 878)
+ {
+ triton1 = 0;
+ printk("bttv: Enabling 430FX compatibilty for bt878\n");
+ pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command);
+ command|=BT878_EN_TBFX;
+ pcibios_write_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, command);
+ pcibios_read_config_byte(btv->bus, btv->devfn, BT878_DEVCTRL, &command);
+ if (!(command&BT878_EN_TBFX))
+ {
+ printk("bttv: 430FX compatibility could not be enabled\n");
+ return -1;
+ }
+ }
+
+ bttv_num++;
+ }
+ if(bttv_num)
+ printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
+ return bttv_num;
+}
+#endif
static void release_bttv(void)
{
@@ -3013,10 +3682,17 @@ static void release_bttv(void)
i2c_unregister_bus((&btv->i2c));
/* disable PCI bus-mastering */
+#if LINUX_VERSION_CODE >= 0x020100
pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
/* Should this be &=~ ?? */
- command|=PCI_COMMAND_MASTER;
+ command&=~PCI_COMMAND_MASTER;
pci_write_config_byte(btv->dev, PCI_COMMAND, command);
+#else
+ pcibios_read_config_byte(btv->bus, btv->devfn, PCI_COMMAND, &command);
+ command&=~PCI_COMMAND_MASTER;
+ pcibios_write_config_byte(btv->bus, btv->devfn, PCI_COMMAND, command);
+
+#endif
/* unmap and free memory */
if (btv->grisc)
@@ -3046,7 +3722,7 @@ static void release_bttv(void)
video_unregister_device(&btv->video_dev);
if(btv->vbi_dev.minor!=-1)
video_unregister_device(&btv->vbi_dev);
- if (radio && btv->radio_dev.minor != -1)
+ if (radio[btv->nr] && btv->radio_dev.minor != -1)
video_unregister_device(&btv->radio_dev);
}
}
@@ -3074,6 +3750,7 @@ int init_bttv_cards(struct video_init *unused)
return -EIO;
}
}
+
return 0;
}
diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h
index f780de12b..ba6c52af4 100644
--- a/drivers/char/bttv.h
+++ b/drivers/char/bttv.h
@@ -21,7 +21,7 @@
#ifndef _BTTV_H_
#define _BTTV_H_
-#define TEST_VBI
+#define BTTV_VERSION_CODE 0x000523
#include <linux/types.h>
#include <linux/wait.h>
@@ -31,8 +31,13 @@
#include "bt848.h"
#include <linux/videodev.h>
+#ifndef O_NONCAP
+#define O_NONCAP O_TRUNC
+#endif
+
#define MAX_GBUFFERS 2
#define RISCMEM_LEN (32744*2)
+#define VBIBUF_SIZE 65536
/* maximum needed buffer size for extended VBI frame mode capturing */
#define BTTV_MAX_FBUF 0x190000
@@ -56,11 +61,20 @@ struct bttv_window
};
struct bttv_pll_info {
- unsigned int pll_ifreq; /* PLL input frequency */
- unsigned int pll_ofreq; /* PLL output frequency */
- unsigned int pll_crystal; /* Crystal used for input */
- unsigned int pll_current; /* Current programmed ofrq*/
+ unsigned int pll_ifreq; /* PLL input frequency */
+ unsigned int pll_ofreq; /* PLL output frequency */
+ unsigned int pll_crystal; /* Crystal used for input */
+ unsigned int pll_current; /* Currently programmed ofreq */
+};
+
+/* Per-open data for handling multiple opens on one device */
+struct device_open
+{
+ int isopen;
+ int noncapturing;
+ struct bttv *dev;
};
+#define MAX_OPENS 3
struct bttv
{
@@ -70,6 +84,10 @@ struct bttv
struct video_picture picture; /* Current picture params */
struct video_audio audio_dev; /* Current audio params */
+ int user;
+ int capuser;
+ struct device_open open_data[MAX_OPENS];
+
struct i2c_bus i2c;
int have_msp3400;
int have_tuner;
@@ -78,9 +96,12 @@ struct bttv
unsigned int nr;
unsigned short id;
+#if LINUX_VERSION_CODE < 0x020100
unsigned char bus; /* PCI bus the Bt848 is on */
unsigned char devfn;
+#else
struct pci_dev *dev;
+#endif
unsigned char irq; /* IRQ used by Bt848 card */
unsigned char revision;
unsigned int bt848_adr; /* bus address of IO mem returned by PCI BIOS */
@@ -92,7 +113,6 @@ struct bttv
struct bttv_window win;
int type; /* card type */
int audio; /* audio mode */
- int user;
int audio_chip;
int radio;
@@ -115,7 +135,7 @@ struct bttv
struct gbuffer *ogbuffers;
struct gbuffer *egbuffers;
u16 gwidth, gheight, gfmt;
- u16 gwidth_next, gheight_next, gfmt_next;
+ u16 gwidth_next, gheight_next, gfmt_next;
u32 *grisc;
unsigned long gro;
@@ -143,7 +163,6 @@ struct bttv
int i2c_command;
int triton1;
};
-
#endif
/*The following should be done in more portable way. It depends on define
@@ -165,12 +184,11 @@ struct bttv
#define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256])
#define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256])
-#define BTTV_GRAB _IOR('v' , BASE_VIDIOCPRIVATE+2, struct gbuf)
#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)
#define BTTV_PLLSET _IOW('v' , BASE_VIDIOCPRIVATE+3, struct bttv_pll_info)
-#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int)
-#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int)
-#define BTTV_NAGRAVERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
+#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int)
+#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int)
+#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
#define BTTV_PICNR _IOR('v' , BASE_VIDIOCPRIVATE+7, int)
@@ -187,6 +205,8 @@ struct bttv
#define BTTV_HAUPPAUGE878 0x0a
#define BTTV_MIROPRO 0x0b
#define BTTV_ADSTECH_TV 0x0c
+#define BTTV_AVERMEDIA98 0x0d
+#define BTTV_VHX 0x0e
#define AUDIO_TUNER 0x00
#define AUDIO_RADIO 0x01
@@ -199,12 +219,20 @@ struct bttv
#define TDA9850 0x01
#define TDA8425 0x02
+#define TDA9840 0x03
#define I2C_TSA5522 0xc2
+#define I2C_TDA9840 0x84
#define I2C_TDA9850 0xb6
#define I2C_TDA8425 0x82
#define I2C_HAUPEE 0xa0
#define I2C_STBEE 0xae
+#define I2C_VHX 0xc0
+
+#define TDA9840_SW 0x00
+#define TDA9840_LVADJ 0x02
+#define TDA9840_STADJ 0x03
+#define TDA9840_TEST 0x04
#define TDA9850_CON1 0x04
#define TDA9850_CON2 0x05
diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c
index 34651f9e9..d4fc2d7f9 100644
--- a/drivers/char/busmouse.c
+++ b/drivers/char/busmouse.c
@@ -56,6 +56,10 @@
static struct mouse_status mouse;
static int mouse_irq = MOUSE_IRQ;
+#ifdef MODULE
+MODULE_PARM(mouse_irq, "i");
+#endif
+
__initfunc(void bmouse_setup(char *str, int *ints))
{
if (ints[0] > 0)
diff --git a/drivers/char/c-qcam.c b/drivers/char/c-qcam.c
index 6ffb80a54..5f9341eac 100644
--- a/drivers/char/c-qcam.c
+++ b/drivers/char/c-qcam.c
@@ -1,13 +1,9 @@
/*
- * Video4Linux: Colour QuickCam driver
+ * Video4Linux Colour QuickCam driver
+ * Copyright 1997-1998 Philip Blundell <philb@gnu.org>
*
- * Philip Blundell <philb@gnu.org>, December 30 1997
- *
- * Largely untested (seems to work at 24bpp with a bidirectional port,
- * though).
*/
-
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -22,27 +18,47 @@
#include <linux/videodev.h>
#include <asm/uaccess.h>
-#include "c-qcam.h"
+struct qcam_device {
+ struct video_device vdev;
+ struct pardevice *pdev;
+ struct parport *pport;
+ int width, height;
+ int ccd_width, ccd_height;
+ int mode;
+ int contrast, brightness, whitebal;
+ int top, left;
+ unsigned int bidirectional;
+};
+
+/* The three possible QuickCam modes */
+#define QC_MILLIONS 0x18
+#define QC_BILLIONS 0x10
+#define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */
+
+/* The three possible decimations */
+#define QC_DECIMATION_1 0
+#define QC_DECIMATION_2 2
+#define QC_DECIMATION_4 4
-static __inline__ void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
+static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
{
/* note: the QC specs refer to the PCAck pin by voltage, not
software level. PC ports have builtin inverters. */
parport_frob_control(qcam->pport, 8, i?8:0);
}
-static __inline__ unsigned int qcam_ready1(struct qcam_device *qcam)
+static inline unsigned int qcam_ready1(struct qcam_device *qcam)
{
return (parport_read_status(qcam->pport) & 0x8)?1:0;
-
}
-static __inline__ unsigned int qcam_ready2(struct qcam_device *qcam)
+static inline unsigned int qcam_ready2(struct qcam_device *qcam)
{
return (parport_read_data(qcam->pport) & 0x1)?1:0;
}
-static inline unsigned int qcam_await_ready1(struct qcam_device *qcam, int value)
+static unsigned int qcam_await_ready1(struct qcam_device *qcam,
+ int value)
{
unsigned long oldjiffies = jiffies;
unsigned int i;
@@ -68,7 +84,7 @@ static inline unsigned int qcam_await_ready1(struct qcam_device *qcam, int value
return 1;
}
-static inline unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
{
unsigned long oldjiffies = jiffies;
unsigned int i;
@@ -95,7 +111,7 @@ static inline unsigned int qcam_await_ready2(struct qcam_device *qcam, int value
return 1;
}
-static inline int qcam_read_data(struct qcam_device *qcam)
+static int qcam_read_data(struct qcam_device *qcam)
{
unsigned int idata;
qcam_set_ack(qcam, 0);
@@ -179,11 +195,10 @@ static void qc_setup(struct qcam_device *q)
/* Set the brightness. */
qcam_set(q, 11, q->brightness);
- /* Set the height. */
- qcam_set(q, 17, q->height);
-
- /* Set the width. */
- qcam_set(q, 19, q->width/2);
+ /* Set the height and width. These refer to the actual
+ CCD area *before* applying the selected decimation. */
+ qcam_set(q, 17, q->ccd_height);
+ qcam_set(q, 19, q->ccd_width / 2);
/* Set top and left. */
qcam_set(q, 0xd, q->top);
@@ -236,53 +251,24 @@ static unsigned int qcam_read_bytes(struct qcam_device *q, unsigned char *buf, u
if (qcam_await_ready1(q, 0)) return bytes;
lo = (parport_read_status(q->pport) & 0xf0);
qcam_set_ack(q, 0);
- /* flip some bits; cqcam gets this wrong */
- buf[bytes++] = (hi | lo) ^ 0x88;
+ /* flip some bits */
+ buf[bytes++] = (hi | (lo >> 4)) ^ 0x88;
}
}
return bytes;
}
-/* Convert the data the camera gives us into the desired output format.
- At the moment this is a no-op because read_bytes() does all the
- required stuff, for 24bpp at least. */
-static size_t qcam_munge_buffer(struct qcam_device *q, char *inbuf, size_t inlen, char *outbuf, size_t outlen)
-{
- size_t outptr = 0;
- switch (q->bpp)
- {
- case 24:
- while (inlen && (outptr <= (outlen-3)))
- {
- unsigned char r, g, b;
- r = inbuf[0];
- g = inbuf[1];
- b = inbuf[2];
- put_user(r, outbuf+(outptr++));
- put_user(g, outbuf+(outptr++));
- put_user(b, outbuf+(outptr++));
- inlen -= 3;
- inbuf += 3;
- }
- break;
- default:
- printk("c-qcam: can't convert this format (%d).\n", q->bpp);
- return 0;
- }
- return outptr;
-}
+#define BUFSZ 150
static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
{
- unsigned int tbpp = 0, tdecimation = 0, lines, pixelsperline, bitsperxfer;
+ unsigned lines, pixelsperline, bitsperxfer;
unsigned int is_bi_dir = q->bidirectional;
size_t wantlen, outptr = 0;
- char *tmpbuf = kmalloc(768, GFP_KERNEL);
- if (tmpbuf == NULL)
- {
- printk(KERN_ERR "cqcam: couldn't allocate a buffer.\n");
- return -ENOMEM;
- }
+ char tmpbuf[BUFSZ];
+
+ if (verify_area(VERIFY_WRITE, buf, len))
+ return -EFAULT;
/* Wait for camera to become ready */
for (;;)
@@ -290,33 +276,19 @@ static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
int i = qcam_get(q, 41);
if (i == -1) {
qc_setup(q);
- kfree(tmpbuf);
return -EIO;
}
- if (i & 0x80)
- schedule();
- else
+ if ((i & 0x80) == 0)
break;
+ else
+ schedule();
}
- switch (q->bpp)
- {
- case 24: tbpp = QC_24BPP; break;
- case 32: tbpp = QC_32BPP; break;
- case 16: tbpp = QC_16BPP; break;
- default: printk("qcam: Bad bpp.\n");
- }
- switch (q->transfer_scale) {
- case 1: tdecimation = QC_1_1; break;
- case 2: tdecimation = QC_2_1; break;
- case 4: tdecimation = QC_4_1; break;
- default: printk("qcam: Bad decimation.\n");
- }
+ if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
+ return -EIO;
- qcam_set(q, 7, (tbpp | tdecimation) + ((is_bi_dir)?1:0) + 1);
-
- lines = q->height / q->transfer_scale;
- pixelsperline = q->width / q->transfer_scale;
+ lines = q->height;
+ pixelsperline = q->width;
bitsperxfer = (is_bi_dir) ? 24 : 8;
if (is_bi_dir)
@@ -326,33 +298,33 @@ static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
mdelay(3);
qcam_set_ack(q, 0);
if (qcam_await_ready1(q, 1)) {
- kfree(tmpbuf);
qc_setup(q);
return -EIO;
}
qcam_set_ack(q, 1);
if (qcam_await_ready1(q, 0)) {
- kfree(tmpbuf);
qc_setup(q);
return -EIO;
}
}
- wantlen = lines * pixelsperline * q->bpp / 8;
+ wantlen = lines * pixelsperline * 24 / 8;
while (wantlen)
{
- size_t t, s, o;
- s = (wantlen > 768)?768:wantlen;
+ size_t t, s;
+ s = (wantlen > BUFSZ)?BUFSZ:wantlen;
t = qcam_read_bytes(q, tmpbuf, s);
if (outptr < len)
{
- o = qcam_munge_buffer(q, tmpbuf, t, buf + outptr,
- len - outptr);
- outptr += o;
+ size_t sz = len - outptr;
+ if (sz > t) sz = t;
+ if (__copy_to_user(buf+outptr, tmpbuf, sz))
+ break;
+ outptr += sz;
}
wantlen -= t;
- if (t < s)
+ if (t < s)
break;
if (current->need_resched)
schedule();
@@ -366,7 +338,6 @@ static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
if (is_bi_dir)
parport_frob_control(q->pport, 0x20, 0);
qc_setup(q);
- kfree(tmpbuf);
return len;
}
@@ -386,7 +357,6 @@ static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
printk("qcam: no ack after EOF\n");
parport_frob_control(q->pport, 0x20, 0);
qc_setup(q);
- kfree(tmpbuf);
return len;
}
parport_frob_control(q->pport, 0x20, 0);
@@ -396,7 +366,6 @@ static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
{
printk("qcam: no ack to port turnaround\n");
qc_setup(q);
- kfree(tmpbuf);
return len;
}
}
@@ -413,10 +382,7 @@ static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
printk("qcam: bad EOF\n");
}
- kfree(tmpbuf);
-
qcam_write_data(q, 0);
-
return len;
}
@@ -526,7 +492,7 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
p.brightness=qcam->brightness<<8;
p.contrast=qcam->contrast<<8;
p.whiteness=qcam->whitebal<<8;
- p.depth=qcam->bpp;
+ p.depth=24;
p.palette=VIDEO_PALETTE_RGB24;
if(copy_to_user(arg, &p, sizeof(p)))
return -EFAULT;
@@ -538,7 +504,10 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(copy_from_user(&p, arg, sizeof(p)))
return -EFAULT;
- if (p.palette != VIDEO_PALETTE_RGB24)
+ /*
+ * Sanity check args
+ */
+ if (p.depth != 24 || p.palette != VIDEO_PALETTE_RGB24)
return -EINVAL;
/*
@@ -547,7 +516,6 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
qcam->brightness = p.brightness>>8;
qcam->contrast = p.contrast>>8;
qcam->whitebal = p.whiteness>>8;
- qcam->bpp = p.depth;
parport_claim_or_block(qcam->pdev);
qc_setup(qcam);
@@ -557,6 +525,7 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCSWIN:
{
struct video_window vw;
+
if(copy_from_user(&vw, arg,sizeof(vw)))
return -EFAULT;
if(vw.flags)
@@ -568,21 +537,33 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
if(vw.width<80||vw.width>320)
return -EINVAL;
- qcam->width = 320;
- qcam->height = 240;
- qcam->transfer_scale = 4;
+ qcam->width = 80;
+ qcam->height = 60;
+ qcam->mode = QC_DECIMATION_4;
if(vw.width>=160 && vw.height>=120)
{
- qcam->transfer_scale = 2;
+ qcam->width = 160;
+ qcam->height = 120;
+ qcam->mode = QC_DECIMATION_2;
}
if(vw.width>=320 && vw.height>=240)
{
qcam->width = 320;
qcam->height = 240;
- qcam->transfer_scale = 1;
+ qcam->mode = QC_DECIMATION_1;
+ }
+ qcam->mode |= QC_MILLIONS;
+#if 0
+ if(vw.width>=640 && vw.height>=480)
+ {
+ qcam->width = 640;
+ qcam->height = 480;
+ qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
}
- /* Ok we figured out what to use from our wide choice */
+#endif
+ /* Ok we figured out what to use from our
+ wide choice */
parport_claim_or_block(qcam->pdev);
qc_setup(qcam);
parport_release(qcam->pdev);
@@ -593,8 +574,8 @@ static int qcam_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
struct video_window vw;
vw.x=0;
vw.y=0;
- vw.width=qcam->width/qcam->transfer_scale;
- vw.height=qcam->height/qcam->transfer_scale;
+ vw.width=qcam->width;
+ vw.height=qcam->height;
vw.chromakey=0;
vw.flags=0;
if(copy_to_user(arg, &vw, sizeof(vw)))
@@ -677,10 +658,9 @@ static struct qcam_device *qcam_init(struct parport *port)
memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
- q->width = 320;
- q->height = 240;
- q->bpp = 32;
- q->transfer_scale = 1;
+ q->width = q->ccd_width = 320;
+ q->height = q->ccd_height = 240;
+ q->mode = QC_MILLIONS | QC_DECIMATION_1;
q->contrast = 192;
q->brightness = 240;
q->whitebal = 128;
@@ -723,7 +703,7 @@ int init_cqcam(struct parport *port)
parport_release(qcam->pdev);
- printk(KERN_INFO "Connectix Colour Quickcam on %s\n",
+ printk(KERN_INFO "Colour Quickcam found on %s\n",
qcam->pport->name);
if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
@@ -745,11 +725,15 @@ void close_cqcam(struct qcam_device *qcam)
kfree(qcam);
}
+#define BANNER "Connectix Colour Quickcam driver v0.02\n"
+
#ifdef MODULE
int init_module(void)
{
struct parport *port;
+ printk(BANNER);
+
for (port = parport_enumerate(); port; port=port->next)
init_cqcam(port);
@@ -767,6 +751,8 @@ __initfunc(int init_colour_qcams(struct video_init *unused))
{
struct parport *port;
+ printk(BANNER);
+
for (port = parport_enumerate(); port; port=port->next)
init_cqcam(port);
return 0;
diff --git a/drivers/char/c-qcam.h b/drivers/char/c-qcam.h
deleted file mode 100644
index b0dbe3015..000000000
--- a/drivers/char/c-qcam.h
+++ /dev/null
@@ -1,18 +0,0 @@
-struct qcam_device {
- struct video_device vdev;
- struct pardevice *pdev;
- struct parport *pport;
- int width, height;
- int bpp;
- int contrast, brightness, whitebal;
- int transfer_scale;
- int top, left;
- unsigned int bidirectional;
-};
-
-#define QC_1_1 0
-#define QC_2_1 2
-#define QC_4_1 4
-#define QC_16BPP 8
-#define QC_32BPP 16
-#define QC_24BPP 24
diff --git a/drivers/char/console.c b/drivers/char/console.c
index 77d80f241..a589e4a9b 100644
--- a/drivers/char/console.c
+++ b/drivers/char/console.c
@@ -1029,7 +1029,7 @@ static void csi_m(int currcons)
*/
translate = set_translate(charset == 0
? G0_charset
- : G1_charset);
+ : G1_charset,currcons);
disp_ctrl = 0;
toggle_meta = 0;
break;
@@ -1037,7 +1037,7 @@ static void csi_m(int currcons)
* Select first alternate font, let's
* chars < 32 be displayed as ROM chars.
*/
- translate = set_translate(IBMPC_MAP);
+ translate = set_translate(IBMPC_MAP,currcons);
disp_ctrl = 1;
toggle_meta = 0;
break;
@@ -1045,7 +1045,7 @@ static void csi_m(int currcons)
* Select second alternate font, toggle
* high bit before displaying as ROM char.
*/
- translate = set_translate(IBMPC_MAP);
+ translate = set_translate(IBMPC_MAP,currcons);
disp_ctrl = 1;
toggle_meta = 1;
break;
@@ -1221,6 +1221,8 @@ static void setterm_command(int currcons)
break;
case 8: /* store colors as defaults */
def_color = attr;
+ if (hi_font_mask == 0x100)
+ def_color >>= 1;
default_attr(currcons);
update_attr(currcons);
break;
@@ -1328,7 +1330,7 @@ static void restore_cur(int currcons)
color = s_color;
G0_charset = saved_G0;
G1_charset = saved_G1;
- translate = set_translate(charset ? G1_charset : G0_charset);
+ translate = set_translate(charset ? G1_charset : G0_charset,currcons);
update_attr(currcons);
need_wrap = 0;
}
@@ -1343,7 +1345,7 @@ static void reset_terminal(int currcons, int do_clear)
bottom = video_num_lines;
vc_state = ESnormal;
ques = 0;
- translate = set_translate(LAT1_MAP);
+ translate = set_translate(LAT1_MAP,currcons);
G0_charset = LAT1_MAP;
G1_charset = GRAF_MAP;
charset = 0;
@@ -1426,12 +1428,12 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
return;
case 14:
charset = 1;
- translate = set_translate(G1_charset);
+ translate = set_translate(G1_charset,currcons);
disp_ctrl = 1;
return;
case 15:
charset = 0;
- translate = set_translate(G0_charset);
+ translate = set_translate(G0_charset,currcons);
disp_ctrl = 0;
return;
case 24: case 26:
@@ -1738,7 +1740,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
else if (c == 'K')
G0_charset = USER_MAP;
if (charset == 0)
- translate = set_translate(G0_charset);
+ translate = set_translate(G0_charset,currcons);
vc_state = ESnormal;
return;
case ESsetG1:
@@ -1751,7 +1753,7 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
else if (c == 'K')
G1_charset = USER_MAP;
if (charset == 1)
- translate = set_translate(G1_charset);
+ translate = set_translate(G1_charset,currcons);
vc_state = ESnormal;
return;
default:
@@ -1894,7 +1896,7 @@ static int do_con_write(struct tty_struct * tty, int from_user,
if (decim)
insert_char(currcons, 1);
scr_writew(himask ?
- ((attr & ~himask) << 8) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
+ ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
(attr << 8) + tc,
(u16 *) pos);
if (DO_UPDATE && draw_x < 0) {
@@ -2231,6 +2233,12 @@ static int con_open(struct tty_struct *tty, struct file * filp)
return 0;
}
+static void con_close(struct tty_struct *tty, struct file * filp)
+{
+ if (tty->count == 1)
+ tty->driver_data = 0;
+}
+
static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear)
{
int j, k ;
@@ -2292,6 +2300,7 @@ __initfunc(unsigned long con_init(unsigned long kmem_start))
console_driver.termios_locked = console_termios_locked;
console_driver.open = con_open;
+ console_driver.close = con_close;
console_driver.write = con_write;
console_driver.write_room = con_write_room;
console_driver.put_char = con_put_char;
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index 95bb6f204..7e97e1fe7 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -7,6 +7,8 @@
* aeb, 950210
*
* Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
+ *
+ * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
*/
#include <linux/kd.h>
@@ -167,7 +169,7 @@ static unsigned short translations[][256] = {
#define MAX_GLYPH 512 /* Max possible glyph value */
-static int inv_translate;
+static int inv_translate[MAX_NR_CONSOLES];
struct uni_pagedir {
u16 **uni_pgdir[32];
@@ -204,9 +206,9 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
}
}
-unsigned short *set_translate(int m)
+unsigned short *set_translate(int m,int currcons)
{
- inv_translate = m;
+ inv_translate[currcons] = m;
return translations[m];
}
@@ -220,14 +222,13 @@ unsigned short *set_translate(int m)
unsigned char inverse_translate(struct vc_data *conp, int glyph)
{
struct uni_pagedir *p;
-
if (glyph < 0 || glyph >= MAX_GLYPH)
return 0;
else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
- !p->inverse_translations[inv_translate])
+ !p->inverse_translations[inv_translate[conp->vc_num]])
return glyph;
else
- return p->inverse_translations[inv_translate][glyph];
+ return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
}
static void update_user_maps(void)
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 62e31d9c9..a023cdd55 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1,7 +1,7 @@
#define BLOCKMOVE
#define Z_WAKE
static char rcsid[] =
-"$Revision: 2.2.1.8 $$Date: 1998/11/13 12:46:20 $";
+"$Revision: 2.2.1.10 $$Date: 1999/01/20 16:14:29 $";
/*
* linux/drivers/char/cyclades.c
@@ -31,6 +31,14 @@ static char rcsid[] =
* void cleanup_module(void);
*
* $Log: cyclades.c,v $
+ * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
+ * Removed all unnecessary page-alignement operations in ioremap calls
+ * (ioremap is currently safe for these operations).
+ *
+ * Revision 2.2.1.9 1998/12/30 18:18:30 ivan
+ * Changed access to PLX PCI bridge registers from I/O to MMIO, in
+ * order to make PLX9050-based boards work with certain motherboards.
+ *
* Revision 2.2.1.8 1998/11/13 12:46:20 ivan
* cy_close function now resets (correctly) the tty->closing flag;
* JIFFIES_DIFF macro fixed.
@@ -580,10 +588,8 @@ static char rcsid[] =
#include <linux/pci.h>
#include <linux/version.h>
-#ifdef CONFIG_PROC_FS
#include <linux/stat.h>
#include <linux/proc_fs.h>
-#endif
#define cy_put_user put_user
@@ -777,9 +783,7 @@ static void cyz_poll(unsigned long);
static void show_status(int);
#endif
-#ifdef CONFIG_PROC_FS
static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
-#endif
/* The Cyclades-Z polling cycle is defined by this variable */
static long cyz_polling_cycle = CZ_DEF_POLL;
@@ -1004,13 +1008,13 @@ check_wild_interrupts(void)
* occur during the bootup sequence
*/
timeout = jiffies+(HZ/10);
- while (timeout >= jiffies)
+ while (time_after_eq(timeout, jiffies))
;
cy_triggered = 0; /* Reset after letting things settle */
timeout = jiffies+(HZ/10);
- while (timeout >= jiffies)
+ while (time_after_eq(timeout, jiffies))
;
for (i = 0, mask = 1; i < 16; i++, mask <<= 1) {
@@ -1054,7 +1058,7 @@ get_auto_irq(volatile ucchar *address)
restore_flags(flags);
timeout = jiffies+(HZ/50);
- while (timeout >= jiffies) {
+ while (time_after_eq(timeout, jiffies)) {
if (cy_irq_triggered)
break;
}
@@ -2597,7 +2601,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
schedule_timeout(char_time);
if (signal_pending(current))
break;
- if (timeout && ((orig_jiffies + timeout) < jiffies))
+ if (timeout && time_before(orig_jiffies + timeout, jiffies))
break;
}
current->state = TASK_RUNNING;
@@ -3396,8 +3400,7 @@ get_serial_info(struct cyclades_port * info,
tmp.baud_base = info->baud;
tmp.custom_divisor = 0; /*!!!*/
tmp.hub6 = 0; /*!!!*/
- copy_to_user(retinfo,&tmp,sizeof(*retinfo));
- return 0;
+ return copy_to_user(retinfo,&tmp,sizeof(*retinfo))?-EFAULT:0;
} /* get_serial_info */
@@ -3768,7 +3771,8 @@ static int
get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
{
- copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor));
+ if(copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+ return -EFAULT;
info->mon.int_count = 0;
info->mon.char_count = 0;
info->mon.char_max = 0;
@@ -4461,8 +4465,7 @@ cy_detect_isa(void))
/* probe for CD1400... */
#if !defined(__alpha__)
- cy_isa_address = ioremap((unsigned int)cy_isa_address,
- CyISA_Ywin);
+ cy_isa_address = ioremap((ulong)cy_isa_address, CyISA_Ywin);
#endif
cy_isa_nchan = CyPORTS_PER_CHIP *
cyy_init_card(cy_isa_address,0);
@@ -4545,7 +4548,6 @@ cy_detect_pci(void))
struct pci_dev *pdev = NULL;
unsigned char cyy_rev_id;
- unsigned long pci_intr_ctrl;
unsigned char cy_pci_irq = 0;
uclong cy_pci_addr0, cy_pci_addr1, cy_pci_addr2;
unsigned short i,j,cy_pci_nchan, plx_ver;
@@ -4584,11 +4586,11 @@ cy_detect_pci(void))
pdev->bus->number, pdev->devfn);
printk("rev_id=%d) IRQ%d\n",
cyy_rev_id, (int)cy_pci_irq);
- printk("Cyclom-Y/PCI:found winaddr=0x%lx ioaddr=0x%lx\n",
- (ulong)cy_pci_addr2, (ulong)cy_pci_addr1);
+ printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n",
+ (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
#endif
- cy_pci_addr1 &= PCI_BASE_ADDRESS_IO_MASK;
- cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
+ cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
+ cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
#if defined(__alpha__)
if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
@@ -4596,20 +4598,21 @@ cy_detect_pci(void))
pdev->bus->number, pdev->devfn);
printk("rev_id=%d) IRQ%d\n",
cyy_rev_id, (int)cy_pci_irq);
- printk("Cyclom-Y/PCI:found winaddr=0x%lx ioaddr=0x%lx\n",
- (ulong)cy_pci_addr2, (ulong)cy_pci_addr1);
+ printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n",
+ (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
printk("Cyclom-Y/PCI not supported for low addresses in "
"Alpha systems.\n");
i--;
continue;
}
#else
- cy_pci_addr2 = (ulong) ioremap(cy_pci_addr2, CyPCI_Ywin);
+ cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Yctl);
+ cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ywin);
#endif
#ifdef CY_PCI_DEBUG
- printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ioaddr=0x%lx\n",
- (u_long)cy_pci_addr2, (u_long)cy_pci_addr1);
+ printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
+ (u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
#endif
cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP *
cyy_init_card((volatile ucchar *)cy_pci_addr2, 1));
@@ -4652,7 +4655,7 @@ cy_detect_pci(void))
/* set cy_card */
cy_card[j].base_addr = (ulong)cy_pci_addr2;
- cy_card[j].ctl_addr = 0;
+ cy_card[j].ctl_addr = (ulong)cy_pci_addr0;
cy_card[j].irq = (int) cy_pci_irq;
cy_card[j].bus_index = 1;
cy_card[j].first_line = cy_next_channel;
@@ -4664,20 +4667,16 @@ cy_detect_pci(void))
switch (plx_ver) {
case PLX_9050:
- outw(inw(cy_pci_addr1+0x4c)|0x0040,cy_pci_addr1+0x4c);
- pci_intr_ctrl = (unsigned long)
- (inw(cy_pci_addr1+0x4c)
- | inw(cy_pci_addr1+0x4e)<<16);
+ cy_writew(cy_pci_addr0+0x4c,
+ cy_readw(cy_pci_addr0+0x4c)|0x0040);
break;
case PLX_9060:
case PLX_9080:
default: /* Old boards, use PLX_9060 */
- outw(inw(cy_pci_addr1+0x68)|0x0900,cy_pci_addr1+0x68);
- pci_intr_ctrl = (unsigned long)
- (inw(cy_pci_addr1+0x68)
- | inw(cy_pci_addr1+0x6a)<<16);
+ cy_writew(cy_pci_addr0+0x68,
+ cy_readw(cy_pci_addr0+0x68)|0x0900);
break;
}
@@ -4712,20 +4711,14 @@ cy_detect_pci(void))
#endif
cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
#if !defined(__alpha__)
- cy_pci_addr0 = (unsigned int) ioremap(
- cy_pci_addr0 & PAGE_MASK,
- PAGE_ALIGN(CyPCI_Zctl))
- + (cy_pci_addr0 & (PAGE_SIZE-1));
+ cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl);
#endif
mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *)
cy_pci_addr0)->mail_box_0);
cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
if (mailbox == ZE_V1) {
#if !defined(__alpha__)
- cy_pci_addr2 = (unsigned int) ioremap(
- cy_pci_addr2 & PAGE_MASK,
- PAGE_ALIGN(CyPCI_Ze_win))
- + (cy_pci_addr2 & (PAGE_SIZE-1));
+ cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ze_win);
#endif
if (ZeIndex == NR_CARDS) {
printk("Cyclades-Ze/PCI found at 0x%lx ",
@@ -4741,10 +4734,7 @@ cy_detect_pci(void))
continue;
} else {
#if !defined(__alpha__)
- cy_pci_addr2 = (unsigned int) ioremap(
- cy_pci_addr2 & PAGE_MASK,
- PAGE_ALIGN(CyPCI_Zwin))
- + (cy_pci_addr2 & (PAGE_SIZE-1));
+ cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Zwin);
#endif
}
@@ -4952,7 +4942,6 @@ show_version(void)
__DATE__, __TIME__);
} /* show_version */
-#ifdef CONFIG_PROC_FS
static int
cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
int *eof, void *data)
@@ -5009,7 +4998,6 @@ done:
len = 0;
return len;
}
-#endif
/* The serial driver boot-time initialization code!
@@ -5281,15 +5269,8 @@ cy_init(void))
#endif
}
-#ifdef CONFIG_PROC_FS
ent = create_proc_entry("cyclades", S_IFREG | S_IRUGO, 0);
ent->read_proc = cyclades_get_proc_info;
-#endif
-#if 0
-#ifdef CONFIG_PROC_FS
- proc_register(&proc_root, &cyclades_proc_entry);
-#endif
-#endif
return 0;
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index f4224bd55..8f3ae96e2 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -286,7 +286,8 @@ int pc_init(void);
#ifdef ENABLE_PCI
static int init_PCI(int);
-static int get_PCI_configuration(char, char, unsigned int *, unsigned int *,
+static int get_PCI_configuration(unsigned char, unsigned char,
+ unsigned int *, unsigned int *,
unsigned int *, unsigned int *,
unsigned int *, unsigned int *);
#endif /* ENABLE_PCI */
@@ -2362,10 +2363,10 @@ static void doevent(int crd)
eventbuf = (volatile unchar *)bus_to_virt((ulong)(bd->re_map_membase + tail + ISTART));
}
- /* Get the channel the event occured on */
+ /* Get the channel the event occurred on */
channel = eventbuf[0];
- /* Get the actual event code that occured */
+ /* Get the actual event code that occurred */
event = eventbuf[1];
/* ----------------------------------------------------------------
@@ -4037,7 +4038,7 @@ void epca_setup(char *str, int *ints)
#ifdef ENABLE_PCI
/* --------------------- Begin get_PCI_configuration ---------------------- */
-int get_PCI_configuration(char bus, char device_fn,
+int get_PCI_configuration(unsigned char bus, unsigned char device_fn,
unsigned int *base_addr0, unsigned int *base_addr1,
unsigned int *base_addr2, unsigned int *base_addr3,
unsigned int *base_addr4, unsigned int *base_addr5)
diff --git a/drivers/char/ftape/RELEASE-NOTES b/drivers/char/ftape/RELEASE-NOTES
index dcc250808..03799dbc0 100644
--- a/drivers/char/ftape/RELEASE-NOTES
+++ b/drivers/char/ftape/RELEASE-NOTES
@@ -423,9 +423,7 @@ Another simple bugfix version.
This release is a simple bugfix version.
-- Linux/SMP: ftape *should* work, if you remember to add the symbol __SMP__
- to the Makefile (you know what I'm talking about, if you're playing with
- Linux/SMP :).
+- Linux/SMP: ftape *should* work.
- FC-10/20: Only accepts IRQs 3-7, or 9. If IRQ 9, properly tell the card
to use IRQ 2. Thanks to Greg Crider (gcrider@iclnet.org) for finding and
locating this bug and testing the patch.
diff --git a/drivers/char/ftape/lowlevel/fdc-io.c b/drivers/char/ftape/lowlevel/fdc-io.c
index 9fb9269f8..6890df0fa 100644
--- a/drivers/char/ftape/lowlevel/fdc-io.c
+++ b/drivers/char/ftape/lowlevel/fdc-io.c
@@ -1348,21 +1348,12 @@ int fdc_grab_irq_and_dma(void)
if (fdc.hook == &do_ftape) {
/* Get fast interrupt handler.
*/
-#if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
if (request_irq(fdc.irq, ftape_interrupt,
SA_INTERRUPT, "ft", ftape_id)) {
TRACE_ABORT(-EIO, ft_t_bug,
"Unable to grab IRQ%d for ftape driver",
fdc.irq);
}
-#else
- if (request_irq(fdc.irq, ftape_interrupt, SA_INTERRUPT,
- ftape_id)) {
- TRACE_ABORT(-EIO, ft_t_bug,
- "Unable to grab IRQ%d for ftape driver",
- fdc.irq);
- }
-#endif
if (request_dma(fdc.dma, ftape_id)) {
#if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
free_irq(fdc.irq, ftape_id);
@@ -1373,7 +1364,6 @@ int fdc_grab_irq_and_dma(void)
"Unable to grab DMA%d for ftape driver",
fdc.dma);
}
- enable_irq(fdc.irq);
}
if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
/* Using same dma channel or irq as standard fdc, need
@@ -1395,12 +1385,7 @@ int fdc_release_irq_and_dma(void)
if (fdc.hook == &do_ftape) {
disable_dma(fdc.dma); /* just in case... */
free_dma(fdc.dma);
- disable_irq(fdc.irq);
-#if LINUX_VERSION_CODE >= KERNEL_VER(1,3,70)
free_irq(fdc.irq, ftape_id);
-#else
- free_irq(fdc.irq);
-#endif
}
if (ft_fdc_base != 0x3f0 && (ft_fdc_dma == 2 || ft_fdc_irq == 6)) {
/* Using same dma channel as standard fdc, need to
diff --git a/drivers/char/hfmodem/Config.in b/drivers/char/hfmodem/Config.in
index a23281f3e..9d2799adb 100644
--- a/drivers/char/hfmodem/Config.in
+++ b/drivers/char/hfmodem/Config.in
@@ -1,5 +1,5 @@
comment 'Misc. hamradio protocols'
-tristate 'Shortwave radio modem driver' CONFIG_HFMODEM
+dep_tristate 'Shortwave radio modem driver' CONFIG_HFMODEM $CONFIG_PARPORT
if [ "$CONFIG_HFMODEM" != "n" ]; then
bool ' HFmodem support for Soundblaster and compatible cards' CONFIG_HFMODEM_SBC
bool ' HFmodem support for WSS and Crystal cards' CONFIG_HFMODEM_WSS
diff --git a/drivers/char/hfmodem/main.c b/drivers/char/hfmodem/main.c
index d940bd232..20347f32c 100644
--- a/drivers/char/hfmodem/main.c
+++ b/drivers/char/hfmodem/main.c
@@ -601,7 +601,7 @@ MODULE_PARM_DESC(dma, "dma number (>=4 for SB16/32/64/etc, <=3 for the rest)");
MODULE_PARM(serio, "i");
MODULE_PARM_DESC(serio, "address of serial port to output PTT");
MODULE_PARM(pario, "i");
-MODULE_PARM_DESC(pario, "address of parial port to output PTT");
+MODULE_PARM_DESC(pario, "address of parallel port to output PTT");
MODULE_PARM(midiio, "i");
MODULE_PARM_DESC(midiio, "address of midi (MPU401) port to output PTT");
diff --git a/drivers/char/i2c.c b/drivers/char/i2c.c
index 851929e94..c85b95bc3 100644
--- a/drivers/char/i2c.c
+++ b/drivers/char/i2c.c
@@ -24,9 +24,11 @@ static int scan = 0;
static int verbose = 0;
static int i2c_debug = 0;
+#if LINUX_VERSION_CODE >= 0x020117
MODULE_PARM(scan,"i");
MODULE_PARM(verbose,"i");
MODULE_PARM(i2c_debug,"i");
+#endif
/* ----------------------------------------------------------------------- */
@@ -34,8 +36,10 @@ static struct i2c_bus *busses[I2C_BUS_MAX];
static struct i2c_driver *drivers[I2C_DRIVER_MAX];
static int bus_count = 0, driver_count = 0;
+#ifdef CONFIG_VIDEO_BT848
extern int i2c_tuner_init(void);
extern int msp3400c_init(void);
+#endif
int i2c_init(void)
{
@@ -53,10 +57,10 @@ int i2c_init(void)
static void i2c_attach_device(struct i2c_bus *bus, struct i2c_driver *driver)
{
- unsigned long flags;
struct i2c_device *device;
int i,j,ack=1;
unsigned char addr;
+ LOCK_FLAGS;
/* probe for device */
LOCK_I2C_BUS(bus);
@@ -148,8 +152,8 @@ static void i2c_detach_device(struct i2c_device *device)
int i2c_register_bus(struct i2c_bus *bus)
{
- unsigned long flags;
int i,ack;
+ LOCK_FLAGS;
memset(bus->devices,0,sizeof(bus->devices));
bus->devcount = 0;
@@ -410,6 +414,7 @@ int i2c_write(struct i2c_bus *bus, unsigned char addr,
#ifdef MODULE
+#if LINUX_VERSION_CODE >= 0x020100
EXPORT_SYMBOL(i2c_register_bus);
EXPORT_SYMBOL(i2c_unregister_bus);
EXPORT_SYMBOL(i2c_register_driver);
@@ -424,7 +429,7 @@ EXPORT_SYMBOL(i2c_sendbyte);
EXPORT_SYMBOL(i2c_readbyte);
EXPORT_SYMBOL(i2c_read);
EXPORT_SYMBOL(i2c_write);
-
+#endif
int init_module(void)
{
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
new file mode 100644
index 000000000..58ce881b3
--- /dev/null
+++ b/drivers/char/isicom.c
@@ -0,0 +1,1951 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Original driver code supplied by Multi-Tech
+ *
+ * Changes
+ * 1/9/98 alan@redhat.com Merge to 2.0.x kernel tree
+ * Obtain and use official major/minors
+ * Loader switched to a misc device
+ * (fixed range check bug as a side effect)
+ * Printk clean up
+ * 9/12/98 alan@redhat.com Rough port to 2.1.x
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/termios.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <linux/isicom.h>
+
+static int isicom_refcount = 0;
+static int prev_card = 3; /* start servicing isi_card[0] */
+static struct isi_board * irq_to_board[16] = { NULL, };
+static struct tty_driver isicom_normal, isicom_callout;
+static struct tty_struct * isicom_table[PORT_COUNT] = { NULL, };
+static struct termios * isicom_termios[PORT_COUNT] = { NULL, };
+static struct termios * isicom_termios_locked[PORT_COUNT] = { NULL, };
+
+static struct isi_board isi_card[BOARD_COUNT];
+static struct isi_port isi_ports[PORT_COUNT];
+
+DECLARE_TASK_QUEUE(tq_isicom);
+
+static struct timer_list tx;
+static char re_schedule = 1;
+#ifdef ISICOM_DEBUG
+static unsigned long tx_count = 0;
+#endif
+
+static int ISILoad_open(struct inode *inode, struct file *filp);
+static int ISILoad_release(struct inode *inode, struct file *filp);
+static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+
+static void isicom_tx(unsigned long _data);
+static void isicom_start(struct tty_struct * tty);
+
+static unsigned char * tmp_buf = 0;
+static struct semaphore tmp_buf_sem = MUTEX;
+
+/* baud index mappings from linux defns to isi */
+
+static char linuxb_to_isib[] = {
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,
+ 18, 19
+};
+
+/*
+ * Firmware loader driver specific routines
+ *
+ */
+
+static struct file_operations ISILoad_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* select */
+ ISILoad_ioctl,
+ NULL, /* mmap */
+ ISILoad_open,
+ NULL, /* flush */
+ ISILoad_release,
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+};
+
+struct miscdevice isiloader_device = {
+ ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
+};
+
+
+extern inline int WaitTillCardIsFree(unsigned short base)
+{
+ unsigned long count=0;
+ while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
+ if (inw(base+0xe)&0x1)
+ return 0;
+ else
+ return 1;
+}
+
+static int ISILoad_open(struct inode *inode, struct file *filp)
+{
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISILoad:Firmware loader Opened!!!\n");
+#endif
+ return 0;
+}
+
+static int ISILoad_release(struct inode *inode, struct file *filp)
+{
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISILoad:Firmware loader Close(Release)d\n",);
+#endif
+ return 0;
+}
+
+static int ISILoad_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ unsigned int card, i, j, signature, status;
+ unsigned short word_count, base;
+ bin_frame frame;
+ /* exec_record exec_rec; */
+
+ if(get_user(card, (int *)arg))
+ return -EFAULT;
+
+ if(card < 0 || card >= BOARD_COUNT)
+ return -ENXIO;
+
+ base=isi_card[card].base;
+
+ if(base==0)
+ return -ENXIO; /* disabled or not used */
+
+ switch(cmd) {
+ case MIOCTL_RESET_CARD:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
+
+ inw(base+0x8);
+
+ for(i=jiffies+HZ/100;time_before(jiffies, i););
+
+ outw(0,base+0x8); /* Reset */
+
+ for(j=1;j<=3;j++) {
+ for(i=jiffies+HZ;time_before(jiffies, i););
+ printk(".");
+ }
+ signature=(inw(base+0x4)) & 0xff;
+
+ if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
+#ifdef ISICOM_DEBUG
+ printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
+#endif
+ printk("\nISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+ return -EIO;
+ }
+
+ switch(signature) {
+ case 0xa5:
+ case 0xbb:
+ case 0xdd: isi_card[card].port_count = 8;
+ isi_card[card].shift_count = 12;
+ break;
+
+ case 0xcc: isi_card[card].port_count = 16;
+ isi_card[card].shift_count = 11;
+ break;
+
+ default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+#ifdef ISICOM_DEBUG
+ printk("Sig=0x%x\n",signature);
+#endif
+ return -EIO;
+ }
+ printk("-Done\n");
+ return put_user(signature,(unsigned int*)arg);
+
+ case MIOCTL_LOAD_FIRMWARE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if(copy_from_user(&frame, (void *) arg, sizeof(bin_frame)))
+ return -EFAULT;
+
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ outw(0xf0,base); /* start upload sequence */
+ outw(0x00,base);
+ outw((frame.addr), base);/* lsb of adderess */
+
+ word_count=(frame.count >> 1) + frame.count % 2;
+ outw(word_count, base);
+ InterruptTheCard(base);
+
+ for(i=0;i<=0x2f;i++); /* a wee bit of delay */
+
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ if ((status=inw(base+0x4))!=0) {
+ printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
+ card+1, frame.addr, frame.count, status);
+ return -EIO;
+ }
+ outsw(base, (void *) frame.bin_data, word_count);
+
+ InterruptTheCard(base);
+
+ for(i=0;i<=0x0f;i++); /* another wee bit of delay */
+
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ if ((status=inw(base+0x4))!=0) {
+ printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
+ return -EIO;
+ }
+ return 0;
+
+ case MIOCTL_READ_FIRMWARE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if(copy_from_user(&frame, (void *) arg, sizeof(bin_header)))
+ return -EFAULT;
+
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ outw(0xf1,base); /* start download sequence */
+ outw(0x00,base);
+ outw((frame.addr), base);/* lsb of adderess */
+
+ word_count=(frame.count >> 1) + frame.count % 2;
+ outw(word_count+1, base);
+ InterruptTheCard(base);
+
+ for(i=0;i<=0xf;i++); /* a wee bit of delay */
+
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ if ((status=inw(base+0x4))!=0) {
+ printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n",
+ card+1, frame.addr, frame.count, status);
+ return -EIO;
+ }
+
+ inw(base);
+ insw(base, frame.bin_data, word_count);
+ InterruptTheCard(base);
+
+ for(i=0;i<=0x0f;i++); /* another wee bit of delay */
+
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ if ((status=inw(base+0x4))!=0) {
+ printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
+ return -EIO;
+ }
+
+ if(copy_to_user((void *) arg, &frame, sizeof(bin_frame)))
+ return -EFAULT;
+ return 0;
+
+ case MIOCTL_XFER_CTRL:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (WaitTillCardIsFree(base))
+ return -EIO;
+
+ outw(0xf2, base);
+ outw(0x800, base);
+ outw(0x0, base);
+ outw(0x0, base);
+ InterruptTheCard(base);
+
+ isi_card[card].status |= FIRMWARE_LOADED;
+ return 0;
+
+ default:
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd);
+#endif
+ return -ENOIOCTLCMD;
+
+ }
+
+}
+
+
+/*
+ * ISICOM Driver specific routines ...
+ *
+ */
+
+static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev,
+ const char * routine)
+{
+#ifdef ISICOM_DEBUG
+ static const char * badmagic =
+ KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
+ static const char * badport =
+ KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";
+ if (!port) {
+ printk(badport, kdevname(dev), routine);
+ return 1;
+ }
+ if (port->magic != ISICOM_MAGIC) {
+ printk(badmagic, kdevname(dev), routine);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+extern inline void schedule_bh(struct isi_port * port)
+{
+ queue_task(&port->bh_tqueue, &tq_isicom);
+ mark_bh(ISICOM_BH);
+}
+
+/* Transmitter */
+
+static void isicom_tx(unsigned long _data)
+{
+ short count = (BOARD_COUNT-1), card, base;
+ short txcount, wait, wrd, residue, word_count, cnt;
+ struct isi_port * port;
+ struct tty_struct * tty;
+ unsigned long flags;
+
+#ifdef ISICOM_DEBUG
+ ++tx_count;
+#endif
+
+ /* find next active board */
+ card = (prev_card + 1) & 0x0003;
+ while(count-- > 0) {
+ if (isi_card[card].status & BOARD_ACTIVE)
+ break;
+ card = (card + 1) & 0x0003;
+ }
+ if (!(isi_card[card].status & BOARD_ACTIVE))
+ goto sched_again;
+
+ prev_card = card;
+
+ count = isi_card[card].port_count;
+ port = isi_card[card].ports;
+ base = isi_card[card].base;
+ for (;count > 0;count--, port++) {
+ /* port not active or tx disabled to force flow control */
+ if (!(port->status & ISI_TXOK))
+ continue;
+
+ tty = port->tty;
+ save_flags(flags); cli();
+ txcount = MIN(TX_SIZE, port->xmit_cnt);
+ if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
+ restore_flags(flags);
+ continue;
+ }
+ wait = 200;
+ while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+ if (wait <= 0) {
+ restore_flags(flags);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: isicom_tx:Card(0x%x) found busy.\n",
+ card);
+#endif
+ continue;
+ }
+ if (!(inw(base + 0x02) & (1 << port->channel))) {
+ restore_flags(flags);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: isicom_tx: cannot tx to 0x%x:%d.\n",
+ base, port->channel + 1);
+#endif
+ continue;
+ }
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n",
+ txcount, port->channel+1);
+#endif
+ outw((port->channel << isi_card[card].shift_count) | txcount
+ , base);
+ residue = NO;
+ wrd = 0;
+ while (1) {
+ cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+ if (residue == YES) {
+ residue = NO;
+ if (cnt > 0) {
+ wrd |= (port->xmit_buf[port->xmit_tail] << 8);
+ port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt--;
+ txcount--;
+ cnt--;
+ outw(wrd, base);
+ }
+ else {
+ outw(wrd, base);
+ break;
+ }
+ }
+ if (cnt <= 0) break;
+ word_count = cnt >> 1;
+ outsw(base, port->xmit_buf+port->xmit_tail, word_count);
+ port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
+ (SERIAL_XMIT_SIZE - 1);
+ txcount -= (word_count << 1);
+ port->xmit_cnt -= (word_count << 1);
+ if (cnt & 0x0001) {
+ residue = YES;
+ wrd = port->xmit_buf[port->xmit_tail];
+ port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt--;
+ txcount--;
+ }
+ }
+/*
+ * Replaced the code below with hopefully a faster loop - sameer
+ */
+
+/*
+ while (1) {
+ wrd = port->xmit_buf[port->xmit_tail++];
+ port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt--;
+ if (--txcount > 0) {
+ wrd |= (port->xmit_buf[port->xmit_tail++] << 8);
+ port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt--;
+ outw(wrd, base);
+ if (--txcount <= 0) break;
+ }
+ else {
+ outw(wrd, base);
+ break;
+ }
+ }
+*/
+ InterruptTheCard(base);
+ if (port->xmit_cnt <= 0)
+ port->status &= ~ISI_TXOK;
+ if (port->xmit_cnt <= WAKEUP_CHARS)
+ schedule_bh(port);
+ restore_flags(flags);
+ }
+
+ /* schedule another tx for hopefully in about 10ms */
+sched_again:
+ if (!re_schedule)
+ return;
+ init_timer(&tx);
+ tx.expires = jiffies + HZ/100;
+ tx.data = 0;
+ tx.function = isicom_tx;
+ add_timer(&tx);
+
+ return;
+}
+
+/* Interrupt handlers */
+
+static void do_isicom_bh(void)
+{
+ run_task_queue(&tq_isicom);
+}
+
+
+
+static void isicom_bottomhalf(void * data)
+{
+ struct isi_port * port = (struct isi_port *) data;
+ struct tty_struct * tty = port->tty;
+
+ if (!tty)
+ return;
+
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+ wake_up_interruptible(&tty->write_wait);
+}
+
+/* main interrupt handler routine */
+static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+ struct isi_board * card;
+ struct isi_port * port;
+ struct tty_struct * tty;
+ unsigned short base, header, word_count, count;
+ unsigned char channel;
+ short byte_count;
+
+ card = irq_to_board[irq];
+ if (!card || !(card->status & FIRMWARE_LOADED)) {
+ printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);
+ return;
+ }
+ base = card->base;
+
+ inw(base); /* get the dummy word out */
+ header = inw(base);
+ channel = (header & 0x7800) >> card->shift_count;
+ byte_count = header & 0xff;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM:Intr:(0x%x:%d).\n", base, channel+1);
+#endif
+ if ((channel+1) > card->port_count) {
+ printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
+ base, channel+1);
+ ClearInterrupt(base);
+ return;
+ }
+ port = card->ports + channel;
+ if (!(port->flags & ASYNC_INITIALIZED)) {
+ ClearInterrupt(base);
+ return;
+ }
+
+ tty = port->tty;
+
+ if (header & 0x8000) { /* Status Packet */
+ header = inw(base);
+ switch(header & 0xff) {
+ case 0: /* Change in EIA signals */
+
+ if (port->flags & ASYNC_CHECK_CD) {
+ if (port->status & ISI_DCD) {
+ if (!(header & ISI_DCD)) {
+ /* Carrier has been lost */
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
+#endif
+ port->status &= ~ISI_DCD;
+ if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (port->flags & ASYNC_CALLOUT_NOHUP)))
+ queue_task(&port->hangup_tq,
+ &tq_scheduler);
+ }
+ }
+ else {
+ if (header & ISI_DCD) {
+ /* Carrier has been detected */
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
+#endif
+ port->status |= ISI_DCD;
+ wake_up_interruptible(&port->open_wait);
+ }
+ }
+ }
+ else {
+ if (header & ISI_DCD)
+ port->status |= ISI_DCD;
+ else
+ port->status &= ~ISI_DCD;
+ }
+
+ if (port->flags & ASYNC_CTS_FLOW) {
+ if (port->tty->hw_stopped) {
+ if (header & ISI_CTS) {
+ port->tty->hw_stopped = 0;
+ /* start tx ing */
+ port->status |= (ISI_TXOK | ISI_CTS);
+ schedule_bh(port);
+ }
+ }
+ else {
+ if (!(header & ISI_CTS)) {
+ port->tty->hw_stopped = 1;
+ /* stop tx ing */
+ port->status &= ~(ISI_TXOK | ISI_CTS);
+ }
+ }
+ }
+ else {
+ if (header & ISI_CTS)
+ port->status |= ISI_CTS;
+ else
+ port->status &= ~ISI_CTS;
+ }
+
+ if (header & ISI_DSR)
+ port->status |= ISI_DSR;
+ else
+ port->status &= ~ISI_DSR;
+
+ if (header & ISI_RI)
+ port->status |= ISI_RI;
+ else
+ port->status &= ~ISI_RI;
+
+ break;
+
+ case 1: /* Received Break !!! */
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ break;
+ *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ /* dunno if this is right */
+ *tty->flip.char_buf_ptr++ = 0;
+ tty->flip.count++;
+ if (port->flags & ASYNC_SAK)
+ do_SAK(tty);
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ break;
+
+ case 2: /* Statistics */
+ printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");
+ break;
+
+ default:
+ printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
+ break;
+ }
+ }
+ else { /* Data Packet */
+ count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n",
+ count, byte_count);
+#endif
+ word_count = count >> 1;
+ insw(base, tty->flip.char_buf_ptr, word_count);
+ tty->flip.char_buf_ptr += (word_count << 1);
+ byte_count -= (word_count << 1);
+ if (count & 0x0001) {
+ *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
+ byte_count -= 2;
+ }
+ memset(tty->flip.flag_buf_ptr, 0, count);
+ tty->flip.flag_buf_ptr += count;
+ tty->flip.count += count;
+
+ if (byte_count > 0) {
+ printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
+ base, channel+1);
+ while(byte_count > 0) { /* drain out unread xtra data */
+ inw(base);
+ byte_count -= 2;
+ }
+ }
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ }
+ ClearInterrupt(base);
+ return;
+}
+
+ /* called with interrupts disabled */
+static void isicom_config_port(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ struct tty_struct * tty;
+ unsigned long baud;
+ unsigned short channel_setup, wait, base = card->base;
+ unsigned short channel = port->channel, shift_count = card->shift_count;
+ unsigned char flow_ctrl;
+
+ if (!(tty = port->tty) || !tty->termios)
+ return;
+ baud = C_BAUD(tty);
+ if (baud & CBAUDEX) {
+ baud &= ~CBAUDEX;
+
+ /* if CBAUDEX bit is on and the baud is set to either 50 or 75
+ * then the card is programmed for 57.6Kbps or 115Kbps
+ * respectively.
+ */
+
+ if (baud < 1 || baud > 2)
+ port->tty->termios->c_cflag &= ~CBAUDEX;
+ else
+ baud += 15;
+ }
+ if (baud == 15) {
+
+ /* the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
+ * by the set_serial_info ioctl ... this is done by
+ * the 'setserial' utility.
+ */
+
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+ baud++; /* 57.6 Kbps */
+ if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+ baud +=2; /* 115 Kbps */
+ }
+ if (linuxb_to_isib[baud] == -1) {
+ /* hang up */
+ drop_dtr(port);
+ return;
+ }
+ else
+ raise_dtr(port);
+
+ wait = 100;
+ while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
+ if (!wait) {
+ printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at channel setup.\n");
+ return;
+ }
+ outw(0x8000 | (channel << shift_count) |0x03, base);
+ outw(linuxb_to_isib[baud] << 8 | 0x03, base);
+ channel_setup = 0;
+ switch(C_CSIZE(tty)) {
+ case CS5:
+ channel_setup |= ISICOM_CS5;
+ break;
+ case CS6:
+ channel_setup |= ISICOM_CS6;
+ break;
+ case CS7:
+ channel_setup |= ISICOM_CS7;
+ break;
+ case CS8:
+ channel_setup |= ISICOM_CS8;
+ break;
+ }
+
+ if (C_CSTOPB(tty))
+ channel_setup |= ISICOM_2SB;
+
+ if (C_PARENB(tty))
+ channel_setup |= ISICOM_EVPAR;
+ if (C_PARODD(tty))
+ channel_setup |= ISICOM_ODPAR;
+ outw(channel_setup, base);
+ InterruptTheCard(base);
+
+ if (C_CLOCAL(tty))
+ port->flags &= ~ASYNC_CHECK_CD;
+ else
+ port->flags |= ASYNC_CHECK_CD;
+
+ /* flow control settings ...*/
+ flow_ctrl = 0;
+ port->flags &= ~ASYNC_CTS_FLOW;
+ if (C_CRTSCTS(tty)) {
+ port->flags |= ASYNC_CTS_FLOW;
+ flow_ctrl |= ISICOM_CTSRTS;
+ }
+ if (I_IXON(tty))
+ flow_ctrl |= ISICOM_RESPOND_XONXOFF;
+ if (I_IXOFF(tty))
+ flow_ctrl |= ISICOM_INITIATE_XONXOFF;
+
+ wait = 100;
+ while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
+ if (!wait) {
+ printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at flow setup.\n");
+ return;
+ }
+ outw(0x8000 | (channel << shift_count) |0x04, base);
+ outw(flow_ctrl << 8 | 0x05, base);
+ outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
+ InterruptTheCard(base);
+
+ /* rx enabled -> enable port for rx on the card */
+ if (C_CREAD(tty)) {
+ card->port_status |= (1 << channel);
+ outw(card->port_status, base + 0x02);
+ }
+
+}
+
+/* open et all */
+
+extern inline void isicom_setup_board(struct isi_board * bp)
+{
+ int channel;
+ struct isi_port * port;
+ unsigned long flags;
+
+ if (bp->status & BOARD_ACTIVE)
+ return;
+ port = bp->ports;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts start, port_count %d...\n", bp->port_count);
+#endif
+ for(channel = 0; channel < bp->port_count; channel++, port++) {
+ save_flags(flags); cli();
+ drop_dtr_rts(port);
+ restore_flags(flags);
+ }
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts stop...\n");
+#endif
+
+ bp->status |= BOARD_ACTIVE;
+ MOD_INC_USE_COUNT;
+ return;
+}
+
+static int isicom_setup_port(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ unsigned long flags;
+
+ if (port->flags & ASYNC_INITIALIZED)
+ return 0;
+ if (!port->xmit_buf) {
+ unsigned long page;
+
+ if (!(page = get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+
+ if (port->xmit_buf) {
+ free_page(page);
+ return -ERESTARTSYS;
+ }
+ port->xmit_buf = (unsigned char *) page;
+ }
+ save_flags(flags); cli();
+ if (port->tty)
+ clear_bit(TTY_IO_ERROR, &port->tty->flags);
+ if (port->count == 1)
+ card->count++;
+
+ port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+
+ /* discard any residual data */
+ kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
+
+ isicom_config_port(port);
+ port->flags |= ASYNC_INITIALIZED;
+
+ restore_flags(flags);
+
+ return 0;
+}
+
+static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port)
+{
+ int do_clocal = 0, retval;
+ struct wait_queue wait = { current, NULL };
+
+ /* block if port is in the process of being closed */
+
+ if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
+#endif
+ interruptible_sleep_on(&port->close_wait);
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ return -EAGAIN;
+ else
+ return -ERESTARTSYS;
+ }
+
+ /* trying to open a callout device... check for constraints */
+
+ if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: bl_ti_rdy: callout open.\n");
+#endif
+ if (port->flags & ASYNC_NORMAL_ACTIVE)
+ return -EBUSY;
+ if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (port->flags & ASYNC_SESSION_LOCKOUT) &&
+ (port->session != current->session))
+ return -EBUSY;
+
+ if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+ (port->flags & ASYNC_PGRP_LOCKOUT) &&
+ (port->pgrp != current->pgrp))
+ return -EBUSY;
+ port->flags |= ASYNC_CALLOUT_ACTIVE;
+ cli();
+ raise_dtr_rts(port);
+ sti();
+ return 0;
+ }
+
+ /* if non-blocking mode is set ... */
+
+ if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
+#endif
+ if (port->flags & ASYNC_CALLOUT_ACTIVE)
+ return -EBUSY;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+ }
+
+ if (port->flags & ASYNC_CALLOUT_ACTIVE) {
+ if (port->normal_termios.c_cflag & CLOCAL)
+ do_clocal = 1;
+ } else {
+ if (C_CLOCAL(tty))
+ do_clocal = 1;
+ }
+#ifdef ISICOM_DEBUG
+ if (do_clocal)
+ printk(KERN_DEBUG "ISICOM: block_til_ready: CLOCAL set.\n");
+#endif
+
+ /* block waiting for DCD to be asserted, and while
+ callout dev is busy */
+ retval = 0;
+ add_wait_queue(&port->open_wait, &wait);
+ cli();
+ if (!tty_hung_up_p(filp))
+ port->count--;
+ sti();
+ port->blocked_open++;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready: waiting for DCD...\n");
+#endif
+ while (1) {
+ cli();
+ if (!(port->flags & ASYNC_CALLOUT_ACTIVE))
+ raise_dtr_rts(port);
+
+ sti();
+ current->state = TASK_INTERRUPTIBLE;
+ if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {
+ if (port->flags & ASYNC_HUP_NOTIFY)
+ retval = -EAGAIN;
+ else
+ retval = -ERESTARTSYS;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready: tty_hung_up_p || not init.\n");
+#endif
+ break;
+ }
+ if (!(port->flags & ASYNC_CALLOUT_ACTIVE) &&
+ !(port->flags & ASYNC_CLOSING) &&
+ (do_clocal || (port->status & ISI_DCD))) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready: do_clocal || DCD.\n");
+#endif
+ break;
+ }
+ if (signal_pending(current)) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready: sig blocked.\n");
+#endif
+ retval = -ERESTARTSYS;
+ break;
+ }
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&port->open_wait, &wait);
+ if (!tty_hung_up_p(filp))
+ port->count++;
+ port->blocked_open--;
+ if (retval)
+ return retval;
+ port->flags |= ASYNC_NORMAL_ACTIVE;
+ return 0;
+}
+
+static int isicom_open(struct tty_struct * tty, struct file * filp)
+{
+ struct isi_port * port;
+ struct isi_board * card;
+ unsigned int line, board;
+ unsigned long flags;
+ int error;
+
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: open start!!!.\n");
+#endif
+ line = MINOR(tty->device) - tty->driver.minor_start;
+
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "line = %d.\n", line);
+#endif
+
+ if ((line < 0) || (line > (PORT_COUNT-1)))
+ return -ENODEV;
+ board = BOARD(line);
+
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "board = %d.\n", board);
+#endif
+
+ card = &isi_card[board];
+ if (!(card->status & FIRMWARE_LOADED)) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG"ISICOM: Firmware not loaded to card%d.\n", board);
+#endif
+ return -ENODEV;
+ }
+
+ /* open on higher 8 dev files on a 8 port card !!! */
+ if (card->port_count == 8)
+ if (line > ((board * 16)+7)) {
+ printk(KERN_ERR "ISICOM: Opened >8 on a 8 port card.\n");
+ return -ENODEV;
+ }
+ port = &isi_ports[line];
+ if (isicom_paranoia_check(port, tty->device, "isicom_open"))
+ return -ENODEV;
+
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: isicom_setup_board ...\n");
+#endif
+ isicom_setup_board(card);
+
+ port->count++;
+ tty->driver_data = port;
+ port->tty = tty;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: isicom_setup_port ...\n");
+#endif
+ if ((error = isicom_setup_port(port))!=0)
+ return error;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: block_til_ready ...\n");
+#endif
+ if ((error = block_til_ready(tty, filp, port))!=0)
+ return error;
+
+ if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = port->normal_termios;
+ else
+ *tty->termios = port->callout_termios;
+ save_flags(flags); cli();
+ isicom_config_port(port);
+ restore_flags(flags);
+ }
+
+ port->session = current->session;
+ port->pgrp = current->pgrp;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: open end!!!.\n");
+#endif
+ return 0;
+}
+
+/* close et all */
+
+extern inline void isicom_shutdown_board(struct isi_board * bp)
+{
+ int channel;
+ struct isi_port * port;
+
+ if (!(bp->status & BOARD_ACTIVE))
+ return;
+ bp->status &= ~BOARD_ACTIVE;
+ port = bp->ports;
+ for(channel = 0; channel < bp->port_count; channel++, port++) {
+ drop_dtr_rts(port);
+ }
+ MOD_DEC_USE_COUNT;
+}
+
+static void isicom_shutdown_port(struct isi_port * port)
+{
+ struct isi_board * card = port->card;
+ struct tty_struct * tty;
+
+ if (!(port->flags & ASYNC_INITIALIZED))
+ return;
+ if (port->xmit_buf) {
+ free_page((unsigned long) port->xmit_buf);
+ port->xmit_buf = NULL;
+ }
+ if (!(tty = port->tty) || C_HUPCL(tty))
+ /* drop dtr on this port */
+ drop_dtr(port);
+
+ /* any other port uninits */
+
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
+ port->flags &= ~ASYNC_INITIALIZED;
+
+ if (--card->count < 0) {
+ printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
+ card->base, card->count);
+ card->count = 0;
+ }
+
+ /* last port was closed , shutdown that boad too */
+ if (!card->count)
+ isicom_shutdown_board(card);
+}
+
+static void isicom_close(struct tty_struct * tty, struct file * filp)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_board * card = port->card;
+ unsigned long flags;
+
+ if (!port)
+ return;
+ if (isicom_paranoia_check(port, tty->device, "isicom_close"))
+ return;
+
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
+#endif
+
+ save_flags(flags); cli();
+ if (tty_hung_up_p(filp)) {
+ restore_flags(flags);
+ return;
+ }
+
+ if ((tty->count == 1) && (port->count != 1)) {
+ printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
+ "tty->count = 1 port count = %d.\n",
+ card->base, port->count);
+ port->count = 1;
+ }
+ if (--port->count < 0) {
+ printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
+ "channel%d = %d", card->base, port->channel,
+ port->count);
+ port->count = 0;
+ }
+
+ if (port->count) {
+ restore_flags(flags);
+ return;
+ }
+ port->flags |= ASYNC_CLOSING;
+ /*
+ * save termios struct since callout and dialin termios may be
+ * different.
+ */
+ if (port->flags & ASYNC_NORMAL_ACTIVE)
+ port->normal_termios = *tty->termios;
+ if (port->flags & ASYNC_CALLOUT_ACTIVE)
+ port->callout_termios = *tty->termios;
+
+ tty->closing = 1;
+ if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+ tty_wait_until_sent(tty, port->closing_wait);
+ /* indicate to the card that no more data can be received
+ on this port */
+ if (port->flags & ASYNC_INITIALIZED) {
+ card->port_status &= ~(1 << port->channel);
+ outw(card->port_status, card->base + 0x02);
+ }
+ isicom_shutdown_port(port);
+ if (tty->driver.flush_buffer)
+ tty->driver.flush_buffer(tty);
+ if (tty->ldisc.flush_buffer)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ port->tty = 0;
+ if (port->blocked_open) {
+ if (port->close_delay) {
+ current->state = TASK_INTERRUPTIBLE;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
+#endif
+ schedule_timeout(port->close_delay);
+ }
+ wake_up_interruptible(&port->open_wait);
+ }
+ port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
+ ASYNC_CLOSING);
+ wake_up_interruptible(&port->close_wait);
+ restore_flags(flags);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: Close end!!!.\n");
+#endif
+}
+
+/* write et all */
+static int isicom_write(struct tty_struct * tty, int from_user,
+ const unsigned char * buf, int count)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ unsigned long flags;
+ int cnt, total = 0;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
+ port->channel+1, count);
+#endif
+ if (isicom_paranoia_check(port, tty->device, "isicom_write"))
+ return 0;
+
+ if (!tty || !port->xmit_buf || !tmp_buf)
+ return 0;
+ if (from_user)
+ down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
+
+ save_flags(flags);
+ while(1) {
+ cli();
+ cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - port->xmit_head));
+ if (cnt <= 0)
+ break;
+
+ if (from_user) {
+ /* the following may block for paging... hence
+ enabling interrupts but tx routine may have
+ created more space in xmit_buf when the ctrl
+ gets back here */
+ sti();
+ copy_from_user(tmp_buf, buf, cnt);
+ cli();
+ cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - port->xmit_head));
+ memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
+ }
+ else
+ memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
+ port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt += cnt;
+ restore_flags(flags);
+ buf += cnt;
+ count -= cnt;
+ total += cnt;
+ }
+ if (from_user)
+ up(&tmp_buf_sem);
+ if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
+ port->status |= ISI_TXOK;
+ restore_flags(flags);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.\n", total);
+#endif
+ return total;
+}
+
+/* put_char et all */
+static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ unsigned long flags;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
+ return;
+
+ if (!tty || !port->xmit_buf)
+ return;
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
+#endif
+
+ save_flags(flags); cli();
+
+ if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
+ restore_flags(flags);
+ return;
+ }
+
+ port->xmit_buf[port->xmit_head++] = ch;
+ port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
+ port->xmit_cnt++;
+ restore_flags(flags);
+}
+
+/* flush_chars et all */
+static void isicom_flush_chars(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_flush_chars"))
+ return;
+
+ if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+ !port->xmit_buf)
+ return;
+
+ /* this tells the transmitter to consider this port for
+ data output to the card ... that's the best we can do. */
+ port->status |= ISI_TXOK;
+}
+
+/* write_room et all */
+static int isicom_write_room(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ int free;
+ if (isicom_paranoia_check(port, tty->device, "isicom_write_room"))
+ return 0;
+
+ free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+ if (free < 0)
+ free = 0;
+ return free;
+}
+
+/* chars_in_buffer et all */
+static int isicom_chars_in_buffer(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ if (isicom_paranoia_check(port, tty->device, "isicom_chars_in_buffer"))
+ return 0;
+ return port->xmit_cnt;
+}
+
+/* ioctl et all */
+extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
+{
+ struct isi_board * card = port->card;
+ short wait = 10;
+ unsigned short base = card->base;
+ unsigned long flags;
+
+ save_flags(flags); cli();
+ while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
+ if (!wait) {
+ printk(KERN_DEBUG "ISICOM: Card found busy in isicom_send_break.\n");
+ return;
+ }
+ outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
+ outw((length & 0xff) << 8 | 0x00, base);
+ outw((length & 0xff00), base);
+ InterruptTheCard(base);
+ restore_flags(flags);
+}
+
+static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
+{
+ /* just send the port status */
+ unsigned int info;
+ unsigned short status = port->status;
+
+ info = ((status & ISI_RTS) ? TIOCM_RTS : 0) |
+ ((status & ISI_DTR) ? TIOCM_DTR : 0) |
+ ((status & ISI_DCD) ? TIOCM_CAR : 0) |
+ ((status & ISI_DSR) ? TIOCM_DSR : 0) |
+ ((status & ISI_CTS) ? TIOCM_CTS : 0) |
+ ((status & ISI_RI ) ? TIOCM_RI : 0);
+ put_user(info, (unsigned long *) value);
+ return 0;
+}
+
+static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
+ unsigned int * value)
+{
+ unsigned int arg;
+ unsigned long flags;
+
+ if(get_user(arg, value))
+ return -EFAULT;
+
+ save_flags(flags); cli();
+
+ switch(cmd) {
+ case TIOCMBIS:
+ if (arg & TIOCM_RTS)
+ raise_rts(port);
+ if (arg & TIOCM_DTR)
+ raise_dtr(port);
+ break;
+
+ case TIOCMBIC:
+ if (arg & TIOCM_RTS)
+ drop_rts(port);
+ if (arg & TIOCM_DTR)
+ drop_dtr(port);
+ break;
+
+ case TIOCMSET:
+ if (arg & TIOCM_RTS)
+ raise_rts(port);
+ else
+ drop_rts(port);
+
+ if (arg & TIOCM_DTR)
+ raise_dtr(port);
+ else
+ drop_dtr(port);
+ break;
+
+ default:
+ restore_flags(flags);
+ return -EINVAL;
+ }
+ restore_flags(flags);
+ return 0;
+}
+
+static int isicom_set_serial_info(struct isi_port * port,
+ struct serial_struct * info)
+{
+ struct serial_struct newinfo;
+ unsigned long flags;
+ int reconfig_port;
+
+ if(copy_from_user(&newinfo, info, sizeof(newinfo)))
+ return -EFAULT;
+
+ reconfig_port = ((port->flags & ASYNC_SPD_MASK) !=
+ (newinfo.flags & ASYNC_SPD_MASK));
+
+ if (!suser()) {
+ if ((newinfo.close_delay != port->close_delay) ||
+ (newinfo.closing_wait != port->closing_wait) ||
+ ((newinfo.flags & ~ASYNC_USR_MASK) !=
+ (port->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
+ (newinfo.flags & ASYNC_USR_MASK));
+ }
+ else {
+ port->close_delay = newinfo.close_delay;
+ port->closing_wait = newinfo.closing_wait;
+ port->flags = ((port->flags & ~ASYNC_FLAGS) |
+ (newinfo.flags & ASYNC_FLAGS));
+ }
+ if (reconfig_port) {
+ save_flags(flags); cli();
+ isicom_config_port(port);
+ restore_flags(flags);
+ }
+ return 0;
+}
+
+static int isicom_get_serial_info(struct isi_port * port,
+ struct serial_struct * info)
+{
+ struct serial_struct out_info;
+
+ memset(&out_info, 0, sizeof(out_info));
+/* out_info.type = ? */
+ out_info.line = port - isi_ports;
+ out_info.port = port->card->base;
+ out_info.irq = port->card->irq;
+ out_info.flags = port->flags;
+/* out_info.baud_base = ? */
+ out_info.close_delay = port->close_delay;
+ out_info.closing_wait = port->closing_wait;
+ if(copy_to_user(info, &out_info, sizeof(out_info)))
+ return -EFAULT;
+ return 0;
+}
+
+static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ int retval;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_ioctl"))
+ return -ENODEV;
+
+ switch(cmd) {
+ case TCSBRK:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ if (!arg)
+ isicom_send_break(port, HZ/4);
+ return 0;
+
+ case TCSBRKP:
+ retval = tty_check_change(tty);
+ if (retval)
+ return retval;
+ tty_wait_until_sent(tty, 0);
+ isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+ return 0;
+
+ case TIOCGSOFTCAR:
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+
+ case TIOCSSOFTCAR:
+ if(get_user(arg, (unsigned long *) arg))
+ return -EFAULT;
+ tty->termios->c_cflag =
+ ((tty->termios->c_cflag & ~CLOCAL) |
+ (arg ? CLOCAL : 0));
+ return 0;
+
+ case TIOCMGET:
+ return isicom_get_modem_info(port, (unsigned int*) arg);
+
+ case TIOCMBIS:
+ case TIOCMBIC:
+ case TIOCMSET:
+ return isicom_set_modem_info(port, cmd,
+ (unsigned int *) arg);
+
+ case TIOCGSERIAL:
+ return isicom_get_serial_info(port,
+ (struct serial_struct *) arg);
+
+ case TIOCSSERIAL:
+ return isicom_set_serial_info(port,
+ (struct serial_struct *) arg);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+/* set_termios et all */
+static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ unsigned long flags;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))
+ return;
+
+ if (tty->termios->c_cflag == old_termios->c_cflag &&
+ tty->termios->c_iflag == old_termios->c_iflag)
+ return;
+
+ save_flags(flags); cli();
+ isicom_config_port(port);
+ restore_flags(flags);
+
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ isicom_start(tty);
+ }
+}
+
+/* throttle et all */
+static void isicom_throttle(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_board * card = port->card;
+ unsigned long flags;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))
+ return;
+
+ /* tell the card that this port cannot handle any more data for now */
+ save_flags(flags); cli();
+ card->port_status &= ~(1 << port->channel);
+ outw(card->port_status, card->base + 0x02);
+ restore_flags(flags);
+}
+
+/* unthrottle et all */
+static void isicom_unthrottle(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ struct isi_board * card = port->card;
+ unsigned long flags;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))
+ return;
+
+ /* tell the card that this port is ready to accept more data */
+ save_flags(flags); cli();
+ card->port_status |= (1 << port->channel);
+ outw(card->port_status, card->base + 0x02);
+ restore_flags(flags);
+}
+
+/* stop et all */
+static void isicom_stop(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_stop"))
+ return;
+
+ /* this tells the transmitter not to consider this port for
+ data output to the card. */
+ port->status &= ~ISI_TXOK;
+}
+
+/* start et all */
+static void isicom_start(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_start"))
+ return;
+
+ /* this tells the transmitter to consider this port for
+ data output to the card. */
+ port->status |= ISI_TXOK;
+}
+
+/* hangup et all */
+static void do_isicom_hangup(void * data)
+{
+ struct isi_port * port = (struct isi_port *) data;
+ struct tty_struct * tty;
+
+ tty = port->tty;
+ if (!tty)
+ return;
+
+ tty_hangup(tty);
+}
+
+static void isicom_hangup(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_hangup"))
+ return;
+
+ isicom_shutdown_port(port);
+ port->count = 0;
+ port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+ port->tty = 0;
+ wake_up_interruptible(&port->open_wait);
+}
+
+/* flush_buffer et all */
+static void isicom_flush_buffer(struct tty_struct * tty)
+{
+ struct isi_port * port = (struct isi_port *) tty->driver_data;
+ unsigned long flags;
+
+ if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))
+ return;
+
+ save_flags(flags); cli();
+ port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+ restore_flags(flags);
+
+ wake_up_interruptible(&tty->write_wait);
+ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ tty->ldisc.write_wakeup)
+ (tty->ldisc.write_wakeup)(tty);
+}
+
+
+static int register_ioregion(void)
+{
+ int count, done=0;
+ for (count=0; count < BOARD_COUNT; count++ ) {
+ if (isi_card[count].base) {
+ if (check_region(isi_card[count].base,16)) {
+ printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
+ isi_card[count].base,isi_card[count].base+15,count+1);
+ isi_card[count].base=0;
+ }
+ else {
+ request_region(isi_card[count].base,16,ISICOM_NAME);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+#endif
+ done++;
+ }
+ }
+ }
+ return done;
+}
+
+static void unregister_ioregion(void)
+{
+ int count;
+ for (count=0; count < BOARD_COUNT; count++ )
+ if (isi_card[count].base) {
+ release_region(isi_card[count].base,16);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+#endif
+ }
+}
+
+static int register_drivers(void)
+{
+ int error;
+
+ /* tty driver structure initialization */
+ memset(&isicom_normal, 0, sizeof(struct tty_driver));
+ isicom_normal.magic = TTY_DRIVER_MAGIC;
+ isicom_normal.name = "ttyM";
+ isicom_normal.major = ISICOM_NMAJOR;
+ isicom_normal.minor_start = 0;
+ isicom_normal.num = PORT_COUNT;
+ isicom_normal.type = TTY_DRIVER_TYPE_SERIAL;
+ isicom_normal.subtype = SERIAL_TYPE_NORMAL;
+ isicom_normal.init_termios = tty_std_termios;
+ isicom_normal.init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL |CLOCAL;
+ isicom_normal.flags = TTY_DRIVER_REAL_RAW;
+ isicom_normal.refcount = &isicom_refcount;
+
+ isicom_normal.table = isicom_table;
+ isicom_normal.termios = isicom_termios;
+ isicom_normal.termios_locked = isicom_termios_locked;
+
+ isicom_normal.open = isicom_open;
+ isicom_normal.close = isicom_close;
+ isicom_normal.write = isicom_write;
+ isicom_normal.put_char = isicom_put_char;
+ isicom_normal.flush_chars = isicom_flush_chars;
+ isicom_normal.write_room = isicom_write_room;
+ isicom_normal.chars_in_buffer = isicom_chars_in_buffer;
+ isicom_normal.ioctl = isicom_ioctl;
+ isicom_normal.set_termios = isicom_set_termios;
+ isicom_normal.throttle = isicom_throttle;
+ isicom_normal.unthrottle = isicom_unthrottle;
+ isicom_normal.stop = isicom_stop;
+ isicom_normal.start = isicom_start;
+ isicom_normal.hangup = isicom_hangup;
+ isicom_normal.flush_buffer = isicom_flush_buffer;
+
+ /* callout device */
+
+ isicom_callout = isicom_normal;
+ isicom_callout.name = "cum";
+ isicom_callout.major = ISICOM_CMAJOR;
+ isicom_callout.subtype = SERIAL_TYPE_CALLOUT;
+
+ if ((error=tty_register_driver(&isicom_normal))!=0) {
+ printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
+ error);
+ return error;
+ }
+ if ((error=tty_register_driver(&isicom_callout))!=0) {
+ tty_unregister_driver(&isicom_normal);
+ printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%d\n",
+ error);
+ return error;
+ }
+ return 0;
+}
+
+static void unregister_drivers(void)
+{
+ int error;
+ if ((error=tty_unregister_driver(&isicom_callout))!=0)
+ printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.\n",error);
+ if (tty_unregister_driver(&isicom_normal))
+ printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+}
+
+static int register_isr(void)
+{
+ int count, done=0;
+ for (count=0; count < BOARD_COUNT; count++ ) {
+ if (isi_card[count].base) {
+ if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) {
+ printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",
+ isi_card[count].irq, count+1);
+ release_region(isi_card[count].base,16);
+ isi_card[count].base=0;
+ }
+ else {
+ printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n",
+ count+1, isi_card[count].base, isi_card[count].irq);
+
+ irq_to_board[isi_card[count].irq]=&isi_card[count];
+ done++;
+ }
+ }
+ }
+ return done;
+}
+
+static void unregister_isr(void)
+{
+ int count;
+ for (count=0; count < BOARD_COUNT; count++ )
+ if (isi_card[count].base) {
+ free_irq(isi_card[count].irq, NULL);
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);
+#endif
+ }
+}
+
+static int isicom_init(void)
+{
+ int card, channel, base;
+ struct isi_port * port;
+ unsigned long page;
+
+ if (!tmp_buf) {
+ page = get_free_page(GFP_KERNEL);
+ if (!page) {
+#ifdef ISICOM_DEBUG
+ printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
+#else
+ printk(KERN_ERR "ISICOM: Not enough memory...\n");
+#endif
+ return 0;
+ }
+ tmp_buf = (unsigned char *) page;
+ }
+
+ if (!register_ioregion())
+ {
+ printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
+ free_page((unsigned long)tmp_buf);
+ return 0;
+ }
+ if (register_drivers())
+ {
+ unregister_ioregion();
+ free_page((unsigned long)tmp_buf);
+ return 0;
+ }
+ if (!register_isr())
+ {
+ unregister_drivers();
+ /* ioports already uregistered in register_isr */
+ free_page((unsigned long)tmp_buf);
+ return 0;
+ }
+
+ /* initialize bottom half */
+ init_bh(ISICOM_BH, do_isicom_bh);
+
+
+ memset(isi_ports, 0, sizeof(isi_ports));
+ for (card = 0; card < BOARD_COUNT; card++) {
+ port = &isi_ports[card * 16];
+ isi_card[card].ports = port;
+ base = isi_card[card].base;
+ for (channel = 0; channel < 16; channel++, port++) {
+ port->magic = ISICOM_MAGIC;
+ port->card = &isi_card[card];
+ port->channel = channel;
+ port->normal_termios = isicom_normal.init_termios;
+ port->callout_termios = isicom_callout.init_termios;
+ port->close_delay = 50 * HZ/100;
+ port->closing_wait = 3000 * HZ/100;
+ port->hangup_tq.routine = do_isicom_hangup;
+ port->hangup_tq.data = port;
+ port->bh_tqueue.routine = isicom_bottomhalf;
+ port->bh_tqueue.data = port;
+ port->status = 0;
+
+ /* . . . */
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Insmod can set static symbols so keep these static
+ */
+
+static int io[4];
+static int irq[4];
+
+MODULE_AUTHOR("MultiTech");
+MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM_DESC(io, "I/O ports for the cards");
+MODULE_PARM(irq, "1-4i");
+MODULE_PARM_DESC(irq, "Interrupts for the cards");
+
+int init_module(void)
+{
+ int retval, card;
+
+ for(card=0; card < BOARD_COUNT; card++)
+ {
+ isi_card[card].base=io[card];
+ isi_card[card].irq=irq[card];
+ }
+
+ for (card=0 ;card < BOARD_COUNT; card++) {
+ if (!((isi_card[card].irq==2)||(isi_card[card].irq==3)||
+ (isi_card[card].irq==4)||(isi_card[card].irq==5)||
+ (isi_card[card].irq==7)||(isi_card[card].irq==10)||
+ (isi_card[card].irq==11)||(isi_card[card].irq==12)||
+ (isi_card[card].irq==15))) {
+
+ if (isi_card[card].base) {
+ printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
+ isi_card[card].irq, card+1);
+ isi_card[card].base=0;
+ }
+ }
+ }
+
+ if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
+ printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n");
+ return -EIO;
+ }
+ retval=misc_register(&isiloader_device);
+ if (retval<0) {
+ printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
+ return -EIO;
+ }
+
+ if (!isicom_init()) {
+ if (misc_deregister(&isiloader_device))
+ printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+ return -EIO;
+ }
+
+ init_timer(&tx);
+ tx.expires = jiffies + 1;
+ tx.data = 0;
+ tx.function = isicom_tx;
+ re_schedule = 1;
+ add_timer(&tx);
+
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ re_schedule = 0;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ);
+ disable_bh(ISICOM_BH);
+
+#ifdef ISICOM_DEBUG
+ printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
+#endif
+
+#ifdef ISICOM_DEBUG
+ printk("ISICOM: uregistering isr ...\n");
+#endif
+ unregister_isr();
+
+#ifdef ISICOM_DEBUG
+ printk("ISICOM: unregistering drivers ...\n");
+#endif
+ unregister_drivers();
+
+#ifdef ISICOM_DEBUG
+ printk("ISICOM: unregistering ioregion ...\n");
+#endif
+ unregister_ioregion();
+
+#ifdef ISICOM_DEBUG
+ printk("ISICOM: freeing tmp_buf ...\n");
+#endif
+ free_page((unsigned long)tmp_buf);
+
+#ifdef ISICOM_DEBUG
+ printk("ISICOM: unregistering firmware loader ...\n");
+#endif
+ if (misc_deregister(&isiloader_device))
+ printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+}
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index f52f452b5..a1a6d93a1 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -2311,7 +2311,7 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout)
if (signal_pending(current))
break;
stli_delay(2);
- if (jiffies >= tend)
+ if (time_after_eq(jiffies, tend))
break;
}
}
diff --git a/drivers/char/joystick/Config.in b/drivers/char/joystick/Config.in
index db5585cd1..a41eaac33 100644
--- a/drivers/char/joystick/Config.in
+++ b/drivers/char/joystick/Config.in
@@ -10,9 +10,9 @@ dep_tristate ' Microsoft SideWinder, Genius Digital joysticks and gamepads' CO
dep_tristate ' ThrustMaster DirectConnect joysticks and gamepads' CONFIG_JOY_THRUSTMASTER $CONFIG_JOYSTICK
dep_tristate ' PDPI Lightning 4 gamecards' CONFIG_JOY_LIGHTNING $CONFIG_JOYSTICK
if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate ' NES, SNES, PSX, Multisystem joysticks and gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK
- dep_tristate ' Sega, Multisystem joysticks and gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK
- dep_tristate ' TurboGraFX Multisystem joystick interface' CONFIG_JOY_TURBOGRAFX $CONFIG_JOYSTICK
+ dep_tristate ' NES, SNES, PSX, Multisystem joysticks and gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK $CONFIG_PARPORT
+ dep_tristate ' Sega, Multisystem joysticks and gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK $CONFIG_PARPORT
+ dep_tristate ' TurboGraFX Multisystem joystick interface' CONFIG_JOY_TURBOGRAFX $CONFIG_JOYSTICK $CONFIG_PARPORT
fi
if [ "$CONFIG_AMIGA" = "y" ]; then
dep_tristate ' Amiga joysticks' CONFIG_JOY_AMIGA $CONFIG_JOYSTICK
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 3eb454663..208e07b89 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -202,8 +202,13 @@ void handle_scancode(unsigned char scancode)
tty = ttytab? ttytab[fg_console]: NULL;
if (tty && (!tty->driver_data)) {
- /* This is to workaround ugly bug in tty_io.c, which
- does not do locking when it should */
+ /*
+ * We touch the tty structure via the the ttytab array
+ * without knowing whether or not tty is open, which
+ * is inherently dangerous. We currently rely on that
+ * fact that console_open sets tty->driver_data when
+ * it opens it, and clears it when it closes it.
+ */
tty = NULL;
}
kbd = kbd_table + fg_console;
diff --git a/drivers/char/lp_m68k.c b/drivers/char/lp_m68k.c
index 2660c2ca2..7eecf2965 100644
--- a/drivers/char/lp_m68k.c
+++ b/drivers/char/lp_m68k.c
@@ -41,11 +41,9 @@
#include <linux/major.h>
#include <linux/sched.h>
#include <linux/string.h>
+#include <linux/timer.h>
#include <linux/init.h>
-#include <asm/irq.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#ifdef CONFIG_AMIGA
#ifdef CONFIG_MULTIFACE_III_LP
@@ -58,6 +56,7 @@
#include <linux/malloc.h>
#include <linux/interrupt.h>
+#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -183,6 +182,7 @@ static ssize_t lp_write_interrupt(struct file *file, const char *buf,
struct inode *inode = file->f_dentry->d_inode;
unsigned long total_bytes_written = 0;
unsigned int flags;
+ long timeout;
int rc;
int dev = MINOR(inode->i_rdev);
@@ -211,12 +211,12 @@ static ssize_t lp_write_interrupt(struct file *file, const char *buf,
/* something blocked printing, so we don't want to sleep too long,
in case we have to rekick the interrupt */
- current->timeout = jiffies + LP_TIMEOUT_POLLED;
+ timeout = LP_TIMEOUT_POLLED;
} else {
- current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
+ timeout = LP_TIMEOUT_INTERRUPT;
}
- interruptible_sleep_on(&lp_table[dev]->lp_wait_q);
+ interruptible_sleep_on_timeout(&lp_table[dev]->lp_wait_q, timeout);
restore_flags(flags);
/* we're up again and running. we first disable lp_interrupt(), then
@@ -281,7 +281,7 @@ static ssize_t lp_write_polled(struct file *file, const char *buf,
int dev = MINOR(inode->i_rdev);
#ifdef LP_DEBUG
- if (jiffies-lp_last_call > lp_table[dev]->time) {
+ if (time_after(jiffies, lp_last_call + lp_table[dev]->time)) {
lp_total_chars = 0;
lp_max_count = 1;
}
@@ -336,8 +336,7 @@ static ssize_t lp_write_polled(struct file *file, const char *buf,
lp_total_chars = 0;
#endif
current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + timeout;
- schedule();
+ schedule_timeout(timeout);
}
}
return temp - buf;
@@ -373,14 +372,12 @@ static int lp_open(struct inode *inode, struct file *file)
if (dev >= MAX_LP)
goto out_err;
-#ifdef CONFIG_KMOD
if (!lp_table[dev]) {
char modname[30];
sprintf(modname, "char-major-%d-%d", LP_MAJOR, dev);
request_module(modname);
}
-#endif
if (!lp_table[dev])
goto out_err;
if (!(lp_table[dev]->flags & LP_EXIST))
@@ -530,7 +527,7 @@ void cleanup_module(void)
* (un-)register for hardware drivers
* tab is an inititalised lp_struct, dev the desired minor
* if dev < 0, let the driver choose the first free minor
- * if sucessful return the minor, else -1
+ * if successful return the minor, else -1
*/
int register_parallel(struct lp_struct *tab, int dev)
{
diff --git a/drivers/char/mac_SCC.c b/drivers/char/mac_SCC.c
index 159a8336e..c20e7a9f0 100644
--- a/drivers/char/mac_SCC.c
+++ b/drivers/char/mac_SCC.c
@@ -198,18 +198,6 @@ static SERIALSWITCH SCC_switch = {
};
/*
- * tmp_buf is used as a temporary buffer by serial_write. We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-static struct semaphore tmp_buf_sem = MUTEX;
-
-/*
* This is used to figure out the divisor speeds and the timeouts
*/
static int baud_table[] = {
@@ -771,7 +759,7 @@ static void SCC_init_port( struct m68k_async_struct *info, int type, int channel
/* If console serial line, then enable interrupts. */
if (info->private->is_cons) {
- printk("mac_SCC: console line %lx; enabling interrupt!\n", info);
+ printk("mac_SCC: console line %d; enabling interrupt!\n", info->line);
write_zsreg(info->private->zs_channel, R1,
(EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
write_zsreg(info->private->zs_channel, R9, (NV | MIE));
@@ -784,7 +772,7 @@ static void SCC_init_port( struct m68k_async_struct *info, int type, int channel
* client attached to us asynchronously.
*/
if (info->private->kgdb_channel) {
- printk("mac_SCC: kgdb line %lx; enabling interrupt!\n", info);
+ printk("mac_SCC: kgdb line %d; enabling interrupt!\n", info->line);
kgdb_chaninit(info, 1, info->private->zs_baud);
}
/* Report settings (in m68kserial.c) */
@@ -1141,8 +1129,6 @@ static void SCC_throttle(struct m68k_async_struct *info, int status)
static void SCC_get_serial_info(struct m68k_async_struct * info,
struct serial_struct * retinfo)
{
- struct serial_struct tmp;
-
retinfo->baud_base = info->baud_base;
retinfo->custom_divisor = info->custom_divisor;
}
@@ -1190,8 +1176,7 @@ static unsigned int SCC_get_modem_info(struct m68k_async_struct *info)
static int SCC_set_modem_info(struct m68k_async_struct *info,
int new_dtr, int new_rts)
{
- int error;
- unsigned int arg, bits;
+ unsigned int bits;
bits = (new_rts ? RTS: 0) + (new_dtr ? DTR: 0);
info->private->curregs[5] = (info->private->curregs[5] & ~(DTR | RTS)) | bits;
@@ -1231,7 +1216,6 @@ static int SCC_ioctl(struct tty_struct *tty, struct file * file,
unsigned long arg)
{
int error;
- int retval;
switch (cmd) {
case TIOCSERGETLSR: /* Get line status register */
@@ -1315,9 +1299,9 @@ static void probe_sccs(void)
ZS_CONTROL+ZS_MOVE*n;
zs_channels[n].data = (volatile unsigned char *)ZS_DATA+ZS_MOVE*n;
#else
- zs_channels[n].control = (volatile unsigned char *)
+ zs_channels[n].control = (volatile unsigned char *) /* 2, 0 */
(mac_bi_data.sccbase+ZS_CH_A_FIRST)+ZS_MOVE*n;
- zs_channels[n].data = (volatile unsigned char *)
+ zs_channels[n].data = (volatile unsigned char *) /* 6, 4 */
(mac_bi_data.sccbase+ZS_CH_A_FIRST+ZS_DATA_MOVE)+ZS_MOVE*n;
#endif
zs_soft[n].private = &zs_soft_private[n];
@@ -1405,8 +1389,8 @@ static inline void
rs_cons_check(struct m68k_async_struct *ss, int channel)
{
int i, o, io;
- static consout_registered = 0;
- static msg_printed = 0;
+ static int consout_registered = 0;
+ static int msg_printed = 0;
i = o = io = 0;
@@ -1458,10 +1442,9 @@ volatile int test_done;
/* rs_init inits the driver */
int mac_SCC_init(void)
{
- int channel, line, nr = 0, i;
+ int channel, line, nr = 0;
unsigned long flags;
struct serial_struct req;
- struct m68k_async_struct *info;
printk("Mac68K Z8530 serial driver version 1.01\n");
@@ -1486,7 +1469,7 @@ int mac_SCC_init(void)
for (channel = 0; channel < zs_channels_found; ++channel) {
req.line = channel;
req.type = SER_SCC_MAC;
- req.port = zs_soft[channel].private->zs_channel->control;
+ req.port = (int) zs_soft[channel].private->zs_channel->control;
if ((line = register_serial( &req )) >= 0) {
SCC_init_port( &rs_table[line], req.type, line );
diff --git a/drivers/char/macmouse.c b/drivers/char/macmouse.c
deleted file mode 100644
index b9236bb93..000000000
--- a/drivers/char/macmouse.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Macintosh ADB Mouse driver for Linux
- *
- * 27 Oct 1997 Michael Schmitz
- *
- * Apple mouse protocol according to:
- *
- * Device code shamelessly stolen from:
- */
-/*
- * Atari Mouse Driver for Linux
- * by Robert de Vries (robert@and.nl) 19Jul93
- *
- * 16 Nov 1994 Andreas Schwab
- * Compatibility with busmouse
- * Support for three button mouse (shamelessly stolen from MiNT)
- * third button wired to one of the joystick directions on joystick 1
- *
- * 1996/02/11 Andreas Schwab
- * Module support
- * Allow multiple open's
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/mac_mouse.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
-static struct mouse_status mouse;
-static int mac_mouse_x_threshold = 2, mac_mouse_y_threshold = 2;
-static int mac_mouse_buttons = 0;
-
-extern void (*mac_mouse_interrupt_hook) (char *, int);
-extern int mac_emulate_button2;
-extern int mac_emulate_button3;
-
-extern int console_loglevel;
-
-/*
- * XXX: need to figure out what ADB mouse packets mean ...
- * This is the stuff stolen from the Atari driver ...
- */
-static void mac_mouse_interrupt(char *buf, int nb)
-{
- static int buttons = 7; /* all mouse buttons _up_ !! */
-
- /*
- Handler 1 -- 100cpi original Apple mouse protocol.
- Handler 2 -- 200cpi original Apple mouse protocol.
-
- For Apple's standard one-button mouse protocol the data array will
- contain the following values:
-
- BITS COMMENTS
- data[0] = 0000 0000 ADB packet identifer.
- data[1] = ???? ???? (?)
- data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
- data[3] = bxxx xxxx First button and x-axis motion.
- data[4] = byyy yyyy Second button and y-axis motion.
-
- NOTE: data[0] is confirmed by the parent function and need not be
- checked here.
- */
-
- /*
- Handler 4 -- Apple Extended mouse protocol.
-
- For Apple's 3-button mouse protocol the data array will contain the
- following values:
-
- BITS COMMENTS
- data[0] = 0000 0000 ADB packet identifer.
- data[1] = 0100 0000 Extended protocol register.
- Bits 6-7 are the device id, which should be 1.
- Bits 4-5 are resolution which is in "units/inch".
- The Logitech MouseMan returns these bits clear but it has
- 200/300cpi resolution.
- Bits 0-3 are unique vendor id.
- data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
- Bits 2-3 should be 8 + 4.
- Bits 4-7 should be 3 for a mouse device.
- data[3] = bxxx xxxx Left button and x-axis motion.
- data[4] = byyy yyyy Second button and y-axis motion.
- data[5] = byyy bxxx Third button and fourth button.
- Y is additiona. high bits of y-axis motion.
- X is additional high bits of x-axis motion.
-
- NOTE: data[0] and data[2] are confirmed by the parent function and
- need not be checked here.
- */
-
- /*
- * 'buttons' here means 'button down' states!
- * Button 1 (left) : bit 2, busmouse button 3
- * Button 2 (right) : bit 0, busmouse button 1
- * Button 3 (middle): bit 1, busmouse button 2
- */
-
- /* x/y and buttons swapped */
-
- if (buf[0] == 0) { /* real packet : use buttons? */
-#ifdef DEBUG_ADBMOUSE
- if (console_loglevel >= 8)
- printk("mac_mouse: real data; ");
-#endif
- /* button 1 (left, bit 2) : always significant ! */
- buttons = (buttons&3) | (buf[3] & 0x80 ? 4 : 0); /* 1+2 unchanged */
- /* button 2 (right, bit 0) present ? */
- if ( !mac_emulate_button2 )
- buttons = (buttons&6) | (buf[4] & 0x80 ? 1 : 0); /* 2+3 unchanged */
- /* button 2 (middle) present? */
- /* data valid only if extended mouse format ! (buf[3] = 0 else)*/
- if ( !mac_emulate_button3 && buf[1]&0x40 )
- buttons = (buttons&5) | (buf[5] & 0x80 ? 2 : 0); /* 1+3 unchanged */
- } else { /* fake packet : use 2+3 */
-#ifdef DEBUG_ADBMOUSE
- if (console_loglevel >= 8)
- printk("mac_mouse: fake data; ");
-#endif
- /* we only see state changes here, but the fake driver takes care
- * to preserve state... button 1 state must stay unchanged! */
- buttons = (buttons&4) | ((buf[4] & 0x80 ? 1 : 0) | (buf[5] & 0x80 ? 2 : 0));
- }
-
- add_mouse_randomness(((~buttons & 7) << 16) + ((buf[2]&0x7f) << 8) + (buf[1]&0x7f));
- mouse.buttons = buttons & 7;
- mouse.dx += ((buf[4]&0x7f) < 64 ? (buf[4]&0x7f) : (buf[4]&0x7f)-128 );
- mouse.dy -= ((buf[3]&0x7f) < 64 ? (buf[3]&0x7f) : (buf[3]&0x7f)-128 );
-
-#ifdef DEBUG_ADBMOUSE
- if (console_loglevel >= 8)
- printk(" %X %X %X buttons %x dx %d dy %d \n",
- buf[3], buf[4], buf[5], mouse.buttons, mouse.dx, mouse.dy);
-#endif
-
- mouse.ready = 1;
- wake_up_interruptible(&mouse.wait);
- if (mouse.fasyncptr)
- kill_fasync(mouse.fasyncptr, SIGIO);
-
-}
-
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
- int retval;
-
- retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
- if (retval < 0)
- return retval;
- return 0;
-}
-
-static int release_mouse(struct inode *inode, struct file *file)
-{
- fasync_mouse(-1, file, 0);
- if (--mouse.active)
- return 0;
-
- mac_mouse_interrupt_hook = NULL;
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int open_mouse(struct inode *inode, struct file *file)
-{
- if (mouse.active++)
- return 0;
-
- mouse.ready = 0;
-
- mouse.dx = mouse.dy = 0;
- mac_mouse_buttons = 0;
- MOD_INC_USE_COUNT;
- mac_mouse_interrupt_hook = mac_mouse_interrupt;
- return 0;
-}
-
-static ssize_t write_mouse(struct file *file, const char *buffer,
- size_t count, loff_t *ppos)
-{
- return -EINVAL;
-}
-
-static ssize_t read_mouse(struct file *file, char *buffer, size_t count,
- loff_t *ppos)
-{
- int dx, dy, buttons;
-
- if (count < 3)
- return -EINVAL;
- if (!mouse.ready)
- return -EAGAIN;
- dx = mouse.dx;
- dy = mouse.dy;
- buttons = mouse.buttons;
- if (dx > 127)
- dx = 127;
- else if (dx < -128)
- dx = -128;
- if (dy > 127)
- dy = 127;
- else if (dy < -128)
- dy = -128;
- mouse.dx -= dx;
- mouse.dy -= dy;
- if (mouse.dx == 0 && mouse.dy == 0)
- mouse.ready = 0;
- if (put_user(buttons | 0x80, buffer++) ||
- put_user((char) dx, buffer++) ||
- put_user((char) dy, buffer++))
- return -EFAULT;
- if (count > 3)
- if (clear_user(buffer, count - 3))
- return -EFAULT;
- return count;
-}
-
-static unsigned int mouse_poll(struct file *file, poll_table *wait)
-{
- poll_wait(file, &mouse.wait, wait);
- if (mouse.ready)
- return POLLIN | POLLRDNORM;
- return 0;
-}
-
-struct file_operations mac_mouse_fops = {
- NULL, /* mouse_seek */
- read_mouse,
- write_mouse,
- NULL, /* mouse_readdir */
- mouse_poll,
- NULL, /* mouse_ioctl */
- NULL, /* mouse_mmap */
- open_mouse,
- NULL, /* flush */
- release_mouse,
- NULL,
- fasync_mouse,
-};
-
-#define ADB_MOUSE_MINOR 10
-
-static struct miscdevice mac_mouse = {
- ADB_MOUSE_MINOR, "adbmouse", &mac_mouse_fops
-};
-
-__initfunc(int mac_mouse_init(void))
-{
- mouse.active = 0;
- mouse.ready = 0;
- mouse.wait = NULL;
-
- if (!MACH_IS_MAC)
- return -ENODEV;
-
- printk(KERN_INFO "Macintosh ADB mouse installed.\n");
- misc_register(&mac_mouse);
- return 0;
-}
-
-
-#define MIN_THRESHOLD 1
-#define MAX_THRESHOLD 20 /* more seems not reasonable... */
-
-__initfunc(void mac_mouse_setup(char *str, int *ints))
-{
- if (ints[0] < 1) {
- printk( "mac_mouse_setup: no arguments!\n" );
- return;
- }
- else if (ints[0] > 2) {
- printk( "mac_mouse_setup: too many arguments\n" );
- }
-
- if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD)
- printk( "mac_mouse_setup: bad threshold value (ignored)\n" );
- else {
- mac_mouse_x_threshold = ints[1];
- mac_mouse_y_threshold = ints[1];
- if (ints[0] > 1) {
- if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD)
- printk("mac_mouse_setup: bad threshold value (ignored)\n" );
- else
- mac_mouse_y_threshold = ints[2];
- }
- }
-
-}
-
-#ifdef MODULE
-#include <asm/setup.h>
-
-int init_module(void)
-{
- return mac_mouse_init();
-}
-
-void cleanup_module(void)
-{
- misc_deregister(&mac_mouse);
-}
-#endif
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index f4cd55fdd..6eaa07d23 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -5,22 +5,17 @@
*/
#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/tty.h>
+#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/tpqic02.h>
#include <linux/ftape.h>
#include <linux/malloc.h>
#include <linux/vmalloc.h>
#include <linux/mman.h>
-#include <linux/mm.h>
#include <linux/random.h>
#include <linux/init.h>
#include <linux/joystick.h>
+#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -137,26 +132,49 @@ static ssize_t write_mem(struct file * file, const char * buf,
return do_write_mem(file, __va(p), p, buf, count, ppos);
}
+/*
+ * This should probably be per-architecture in <asm/pgtable.h>
+ */
+static inline unsigned long pgprot_noncached(unsigned long prot)
+{
+#if defined(__i386__)
+ if (boot_cpu_data.x86 > 3)
+ prot |= _PAGE_PCD;
+#elif defined(__powerpc__)
+ prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;
+#elif defined(__mc68000__)
+ if (CPU_IS_020_OR_030)
+ prot |= _PAGE_NOCACHE030;
+ /* Use no-cache mode, serialized */
+ if (CPU_IS_040_OR_060)
+ prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;
+#elif defined(__mips__)
+ prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
+#endif
+
+ return prot;
+}
+
static int mmap_mem(struct file * file, struct vm_area_struct * vma)
{
unsigned long offset = vma->vm_offset;
if (offset & ~PAGE_MASK)
return -ENXIO;
-#if defined(__i386__)
+
/*
- * hmm.. This disables high-memory caching, as the XFree86 team
- * wondered about that at one time.
- * The surround logic should disable caching for the high device
- * addresses anyway, but right now this seems still needed.
+ * Accessing memory above the top the kernel knows about or
+ * through a file pointer that was marked O_SYNC will be
+ * done non-cached.
+ *
+ * Set VM_IO, as this is likely a non-cached access to an
+ * I/O area, and we don't want to include that in a core
+ * file.
*/
- if (boot_cpu_data.x86 > 3 && offset >= __pa(high_memory))
- pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#endif
-#ifdef __powerpc__
- if (offset >= __pa(high_memory))
- pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
-#endif
+ if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC)) {
+ pgprot_val(vma->vm_page_prot) = pgprot_noncached(pgprot_val(vma->vm_page_prot));
+ vma->vm_flags |= VM_IO;
+ }
if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index d449cf226..fe13a043c 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -49,9 +49,7 @@
#include <linux/tty.h>
#include <linux/selection.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
/*
* Head entry for the doubly linked miscdevice list
@@ -89,7 +87,6 @@ extern void hfmodem_init(void);
extern int pc110pad_init(void);
extern int pmu_device_init(void);
-#ifdef CONFIG_PROC_FS
static int misc_read_proc(char *buf, char **start, off_t offset,
int len, int *eof, void *private)
{
@@ -102,7 +99,6 @@ static int misc_read_proc(char *buf, char **start, off_t offset,
return len > offset ? len - offset : 0;
}
-#endif /* PROC_FS */
static int misc_open(struct inode * inode, struct file * file)
{
@@ -113,7 +109,6 @@ static int misc_open(struct inode * inode, struct file * file)
while ((c != &misc_list) && (c->minor != minor))
c = c->next;
if (c == &misc_list) {
-#ifdef CONFIG_KMOD
char modname[20];
sprintf(modname, "char-major-%d-%d", MISC_MAJOR, minor);
request_module(modname);
@@ -121,7 +116,6 @@ static int misc_open(struct inode * inode, struct file * file)
while ((c != &misc_list) && (c->minor != minor))
c = c->next;
if (c == &misc_list)
-#endif
return -ENODEV;
}
@@ -188,17 +182,13 @@ int misc_deregister(struct miscdevice * misc)
EXPORT_SYMBOL(misc_register);
EXPORT_SYMBOL(misc_deregister);
-#if defined(CONFIG_PROC_FS)
static struct proc_dir_entry *proc_misc;
-#endif
int __init misc_init(void)
{
-#ifdef CONFIG_PROC_FS
proc_misc = create_proc_entry("misc", 0, 0);
if (proc_misc)
proc_misc->read_proc = misc_read_proc;
-#endif /* PROC_FS */
#ifdef CONFIG_BUSMOUSE
bus_mouse_init();
#endif
diff --git a/drivers/char/msbusmouse.c b/drivers/char/msbusmouse.c
index b49bfe9a6..07c733b5b 100644
--- a/drivers/char/msbusmouse.c
+++ b/drivers/char/msbusmouse.c
@@ -51,6 +51,10 @@
static struct mouse_status mouse;
static int mouse_irq = MOUSE_IRQ;
+#ifdef MODULE
+MODULE_PARM(mouse_irq, "i");
+#endif
+
__initfunc(void msmouse_setup(char *str, int *ints))
{
if (ints[0] > 0)
diff --git a/drivers/char/msp3400.c b/drivers/char/msp3400.c
index 651d5b733..abf08764d 100644
--- a/drivers/char/msp3400.c
+++ b/drivers/char/msp3400.c
@@ -1,21 +1,21 @@
/*
* programming the msp34* sound processor family
*
- * (c) 1997,1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ * (c) 1997,1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
* what works and what doesn't:
*
- * AM mono
+ * AM-Mono
* probably doesn't (untested)
*
- * FM-mono
- * should work. FM stereo modes are backward-compatible to mono.
- * Therefore FM mono should always be available.
+ * FM-Mono
+ * should work. The stereo modes are backward compatible to FM-mono,
+ * therefore FM-Mono should be allways available.
*
- * FM stereo (B/G, used in Germany)
+ * FM-Stereo (B/G, used in germany)
* should work, with autodetect
*
- * FM stereo (satellite)
+ * FM-Stereo (satellite)
* should work, no autodetect (i.e. default is mono, but you can
* switch to stereo -- untested)
*
@@ -27,9 +27,14 @@
* TODO:
* - better SAT support
*
+ *
+ * 980623 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * using soundcore instead of OSS
+ *
*/
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -37,6 +42,10 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/malloc.h>
+#ifdef __SMP__
+#include <asm/pgtable.h>
+#include <linux/smp_lock.h>
+#endif
/* kernel_thread */
#define __KERNEL_SYSCALLS__
@@ -67,14 +76,14 @@ struct msp3400c {
int mode;
int norm;
int stereo;
+ int main, second; /* sound carrier */
- int mixer;
- int left, right; /* volume */
+ int left, right; /* volume */
int bass, treble;
/* thread */
struct task_struct *thread;
- struct semaphore *wait;
+ struct wait_queue *wq;
struct semaphore *notify;
int active,restart,rmmod;
@@ -88,7 +97,22 @@ struct msp3400c {
#define dprintk if (debug) printk
+#if LINUX_VERSION_CODE < 0x020100
+/* 2.0.x */
+#define signal_pending(current) (current->signal & ~current->blocked)
+#define sigfillset(set)
+#define mdelay(x) udelay(1000*x)
+#else
MODULE_PARM(debug,"i");
+#endif
+
+#if LINUX_VERSION_CODE < 0x02017f
+void schedule_timeout(int j)
+{
+ current->timeout = jiffies + j;
+ schedule();
+}
+#endif
/* ---------------------------------------------------------------------- */
@@ -211,9 +235,9 @@ static struct MSP_INIT_DATA_DEM {
/* FM Radio */
{ { -8, -8, 4, 6, 78, 107 }, { -8, -8, 4, 6, 78, 107 },
MSP_CARRIER(10.7), MSP_CARRIER(10.7),
- 0x00d0, 0x0480, 0x0020, 0x3002 },
+ 0x00d0, 0x0480, 0x0020, 0x3000 },
- /* Terrestial FM-mono */
+ /* Terrestial FM-mono + FM-stereo */
{ { 3, 18, 27, 48, 66, 72 }, { 3, 18, 27, 48, 66, 72 },
MSP_CARRIER(5.5), MSP_CARRIER(5.5),
0x00d0, 0x0480, 0x0030, 0x3000},
@@ -230,7 +254,7 @@ static struct MSP_INIT_DATA_DEM {
/* NICAM I */
{ { 2, 4, -6, -4, 40, 94 }, { 3, 18, 27, 48, 66, 72 },
- MSP_CARRIER(5.5), MSP_CARRIER(5.5),
+ MSP_CARRIER(6.0), MSP_CARRIER(6.0),
0x00d0, 0x0040, 0x0120, 0x3000},
};
@@ -244,7 +268,7 @@ static struct CARRIER_DETECT carrier_detect_main[] = {
{ MSP_CARRIER(4.5), "4.5 NTSC" },
{ MSP_CARRIER(5.5), "5.5 PAL B/G" },
{ MSP_CARRIER(6.0), "6.0 PAL I" },
- { MSP_CARRIER(6.5), "6.5 PAL SAT / SECAM" }
+ { MSP_CARRIER(6.5), "6.5 PAL D/K + SAT + SECAM" }
};
static struct CARRIER_DETECT carrier_detect_55[] = {
@@ -255,6 +279,9 @@ static struct CARRIER_DETECT carrier_detect_55[] = {
static struct CARRIER_DETECT carrier_detect_65[] = {
/* PAL SAT / SECAM */
+ { MSP_CARRIER(5.85), "5.85 PAL D/K NICAM" },
+ { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" },
+ { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" },
{ MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" },
{ MSP_CARRIER(7.20), "7.20 PAL SAT FM-stereo s" },
{ MSP_CARRIER(7.38), "7.38 PAL SAT FM-stereo b" },
@@ -270,6 +297,7 @@ static void msp3400c_setcarrier(struct i2c_bus *bus, int cdo1, int cdo2)
msp3400c_write(bus,I2C_MSP3400C_DEM, 0x009b, cdo1 >> 12);
msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00a3, cdo2 & 0xfff);
msp3400c_write(bus,I2C_MSP3400C_DEM, 0x00ab, cdo2 >> 12);
+ msp3400c_write(bus,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
}
static void msp3400c_setvolume(struct i2c_bus *bus, int left, int right)
@@ -329,12 +357,14 @@ static void msp3400c_setmode(struct msp3400c *msp, int type)
msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0005,
msp_init_data[type].fir2[i]);
- msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
+ msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0083, /* MODE_REG */
msp_init_data[type].mode_reg);
msp3400c_setcarrier(msp->bus, msp_init_data[type].cdo1,
msp_init_data[type].cdo2);
+ msp3400c_write(msp->bus,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/
+
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,
msp_init_data[type].dfp_src);
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,
@@ -357,9 +387,9 @@ static void msp3400c_setstereo(struct msp3400c *msp, int mode)
/* switch demodulator */
switch (msp->mode) {
case MSP_MODE_FM_TERRA:
- dprintk("msp3400: B/G setstereo: %d\n",mode);
+ dprintk("msp3400: FM setstereo: %d\n",mode);
msp->stereo = mode;
- msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.7421875),MSP_CARRIER(5.5));
+ msp3400c_setcarrier(msp->bus,msp->second,msp->main);
switch (mode) {
case VIDEO_SOUND_STEREO:
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000e, 0x3001);
@@ -372,7 +402,7 @@ static void msp3400c_setstereo(struct msp3400c *msp, int mode)
}
break;
case MSP_MODE_FM_SAT:
- dprintk("msp3400: sat setstereo: %d\n",mode);
+ dprintk("msp3400: SAT setstereo: %d\n",mode);
msp->stereo = mode;
switch (mode) {
case VIDEO_SOUND_MONO:
@@ -390,9 +420,10 @@ static void msp3400c_setstereo(struct msp3400c *msp, int mode)
}
break;
case MSP_MODE_FM_NICAM1:
- dprintk("msp3400: NICAM1 setstereo: %d\n",mode);
+ case MSP_MODE_FM_NICAM2:
+ dprintk("msp3400: NICAM setstereo: %d\n",mode);
msp->stereo = mode;
- msp3400c_setcarrier(msp->bus,MSP_CARRIER(5.85),MSP_CARRIER(5.5));
+ msp3400c_setcarrier(msp->bus,msp->second,msp->main);
nicam=0x0100;
break;
default:
@@ -406,7 +437,9 @@ static void msp3400c_setstereo(struct msp3400c *msp, int mode)
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0008,0x0020|nicam);
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0009,0x0020|nicam);
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x000a,0x0020|nicam);
+#if 0
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0005,0x4000);
+#endif
break;
case VIDEO_SOUND_MONO:
case VIDEO_SOUND_LANG1:
@@ -422,6 +455,27 @@ static void msp3400c_setstereo(struct msp3400c *msp, int mode)
}
}
+static void
+msp3400c_print_mode(struct msp3400c *msp)
+{
+ if (msp->main == msp->second) {
+ printk("msp3400: mono sound carrier: %d.%03d MHz\n",
+ msp->main/910000,(msp->main/910)%1000);
+ } else {
+ printk("msp3400: main sound carrier: %d.%03d MHz\n",
+ msp->main/910000,(msp->main/910)%1000);
+ }
+ if (msp->mode == MSP_MODE_FM_NICAM1 ||
+ msp->mode == MSP_MODE_FM_NICAM2)
+ printk("msp3400: NICAM carrier : %d.%03d MHz\n",
+ msp->second/910000,(msp->second/910)%1000);
+ if (msp->mode == MSP_MODE_FM_TERRA &&
+ msp->main != msp->second) {
+ printk("msp3400: FM-stereo carrier : %d.%03d MHz\n",
+ msp->second/910000,(msp->second/910)%1000);
+ }
+}
+
/* ----------------------------------------------------------------------- */
struct REGISTER_DUMP {
@@ -446,21 +500,21 @@ static void msp3400c_stereo_wake(unsigned long data)
{
struct msp3400c *msp = (struct msp3400c*)data; /* XXX alpha ??? */
- if (!msp->active)
- up(msp->wait);
+ wake_up_interruptible(&msp->wq);
}
static int msp3400c_thread(void *data)
{
- unsigned long flags;
struct msp3400c *msp = data;
- struct semaphore sem = MUTEX_LOCKED;
struct CARRIER_DETECT *cd;
int count, max1,max2,val1,val2, val,this;
int newstereo;
+ LOCK_FLAGS;
- /* lock_kernel(); */
+#ifdef __SMP__
+ lock_kernel();
+#endif
exit_mm(current);
current->session = 1;
@@ -469,10 +523,12 @@ static int msp3400c_thread(void *data)
current->fs->umask = 0;
strcpy(current->comm,"msp3400");
- msp->wait = &sem;
+ msp->wq = NULL;
msp->thread = current;
- /* unlock_kernel(); */
+#ifdef __SMP__
+ unlock_kernel();
+#endif
dprintk("msp3400: thread: start\n");
if(msp->notify != NULL)
@@ -481,9 +537,11 @@ static int msp3400c_thread(void *data)
for (;;) {
if (msp->rmmod)
goto done;
- dprintk("msp3400: thread: sleep\n");
- down_interruptible(&sem);
- dprintk("msp3400: thread: wakeup\n");
+ if (debug > 1)
+ printk("msp3400: thread: sleep\n");
+ interruptible_sleep_on(&msp->wq);
+ if (debug > 1)
+ printk("msp3400: thread: wakeup\n");
if (msp->rmmod || signal_pending(current))
goto done;
@@ -510,6 +568,7 @@ static int msp3400c_thread(void *data)
}
break;
case MSP_MODE_FM_NICAM1:
+ case MSP_MODE_FM_NICAM2:
val = msp3400c_read(msp->bus, I2C_MSP3400C_DEM, 0x23);
switch ((val & 0x1e) >> 1) {
case 0:
@@ -553,7 +612,7 @@ static int msp3400c_thread(void *data)
msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
UNLOCK_I2C_BUS(msp->bus);
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ/25);
if (signal_pending(current))
goto done;
@@ -587,7 +646,7 @@ static int msp3400c_thread(void *data)
msp3400c_setcarrier(msp->bus, cd[this].cdo,cd[this].cdo);
UNLOCK_I2C_BUS(msp->bus);
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ/25);
if (signal_pending(current))
goto done;
@@ -603,34 +662,56 @@ static int msp3400c_thread(void *data)
dprintk("msp3400: carrier2 val: %5d / %s\n", val,cd[this].name);
}
- /* program the msp3400 according to the results */
+ /* programm the msp3400 according to the results */
+ msp->main = carrier_detect_main[max1].cdo;
switch (max1) {
- case 0: /* 4.5 */
case 1: /* 5.5 */
- msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
- msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
- carrier_detect_main[max1].cdo);
if (max2 == 0) {
/* B/G FM-stereo */
+ msp->second = carrier_detect_55[max2].cdo;
+ msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
msp->watch_stereo = 1;
- }
- if (max2 == 1 && msp->nicam) {
+ } else if (max2 == 1 && msp->nicam) {
/* B/G NICAM */
+ msp->second = carrier_detect_55[max2].cdo;
msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
- /* msp3400c_write(msp->bus, I2C_MSP3400C_DFP, 0x21, 0x01); */
- msp3400c_setcarrier(msp->bus, MSP_CARRIER(5.85),
- MSP_CARRIER(5.5));
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
msp->watch_stereo = 1;
+ } else {
+ goto no_second;
}
break;
case 2: /* 6.0 */
+ /* PAL I NICAM */
+ msp->second = MSP_CARRIER(6.552);
+ msp3400c_setmode(msp, MSP_MODE_FM_NICAM2);
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
+ msp->watch_stereo = 1;
+ break;
case 3: /* 6.5 */
+ if (max2 == 1 || max2 == 2) {
+ /* D/K FM-stereo */
+ msp->second = carrier_detect_65[max2].cdo;
+ msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
+ msp3400c_setstereo(msp, VIDEO_SOUND_MONO);
+ msp->watch_stereo = 1;
+ } else if (max2 == 0 && msp->nicam) {
+ /* D/K NICAM */
+ msp->second = carrier_detect_65[max2].cdo;
+ msp3400c_setmode(msp, MSP_MODE_FM_NICAM1);
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
+ msp->watch_stereo = 1;
+ } else {
+ goto no_second;
+ }
+ break;
+ case 0: /* 4.5 */
default:
+ no_second:
+ msp->second = carrier_detect_main[max1].cdo;
msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
- msp3400c_setcarrier(msp->bus, carrier_detect_main[max1].cdo,
- carrier_detect_main[max1].cdo);
- msp3400c_setstereo(msp, VIDEO_SOUND_STEREO);
+ msp3400c_setcarrier(msp->bus, msp->second, msp->main);
break;
}
@@ -640,15 +721,18 @@ static int msp3400c_thread(void *data)
if (msp->watch_stereo) {
del_timer(&msp->wake_stereo);
- msp->wake_stereo.expires = jiffies + HZ;
+ msp->wake_stereo.expires = jiffies + 2*HZ;
add_timer(&msp->wake_stereo);
}
+
+ if (debug)
+ msp3400c_print_mode(msp);
+
msp->active = 0;
}
done:
dprintk("msp3400: thread: exit\n");
- msp->wait = NULL;
msp->active = 0;
msp->thread = NULL;
@@ -690,6 +774,7 @@ static int msp3410d_thread(void *data)
goto done;
dprintk("msp3410: thread: sleep\n");
down_interruptible(&sem);
+ sem.owner = 0;
dprintk("msp3410: thread: wakeup\n");
if (msp->rmmod)
goto done;
@@ -713,7 +798,8 @@ static int msp3410d_thread(void *data)
/* wait 1 sec */
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ);
+ current->timeout = jiffies + HZ;
+ schedule();
if (signal_pending(current))
goto done;
if (msp->restart) {
@@ -752,9 +838,14 @@ done:
#ifdef REGISTER_MIXER
+#include <linux/sound.h>
#include <linux/soundcard.h>
-#include <../drivers/sound/sound_config.h>
-#include <../drivers/sound/dev_table.h>
+#include <asm/uaccess.h>
+
+static struct msp3400c *mspmix = NULL; /* ugly hack, should do something more sensible */
+static int mixer_num;
+static int mixer_modcnt = 0;
+static struct semaphore mixer_sem = MUTEX;
static int mix_to_v4l(int i)
{
@@ -787,16 +878,42 @@ static int v4l_to_mix2(int l, int r)
return (r << 8) | l;
}
-static int msp3400c_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+static int
+msp3400c_mixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- struct msp3400c *msp = mixer_devs[dev]->devc;
- unsigned long flags;
int ret,val = 0;
+ LOCK_FLAGS;
+
+ if (cmd == SOUND_MIXER_INFO) {
+ mixer_info info;
+ strncpy(info.id, "MSP3400", sizeof(info.id));
+ strncpy(info.name, "MSP 3400", sizeof(info.name));
+ info.modify_counter = mixer_modcnt;
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == SOUND_OLD_MIXER_INFO) {
+ _old_mixer_info info;
+ strncpy(info.id, "MSP3400", sizeof(info.id));
+ strncpy(info.name, "MSP 3400", sizeof(info.name));
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == OSS_GETVERSION)
+ return put_user(SOUND_VERSION, (int *)arg);
if (_SIOC_DIR(cmd) & _SIOC_WRITE)
if (get_user(val, (int *)arg))
return -EFAULT;
+ down(&mixer_sem);
+ if (!mspmix) {
+ up(&mixer_sem);
+ return -ENODEV;
+ }
+
switch (cmd) {
case MIXER_READ(SOUND_MIXER_RECMASK):
case MIXER_READ(SOUND_MIXER_CAPS):
@@ -813,91 +930,97 @@ static int msp3400c_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
break;
case MIXER_WRITE(SOUND_MIXER_VOLUME):
- msp->left = mix_to_v4l(val);
- msp->right = mix_to_v4l(val >> 8);
- LOCK_I2C_BUS(msp->bus);
- msp3400c_setvolume(msp->bus,msp->left,msp->right);
- UNLOCK_I2C_BUS(msp->bus);
+ mspmix->left = mix_to_v4l(val);
+ mspmix->right = mix_to_v4l(val >> 8);
+ LOCK_I2C_BUS(mspmix->bus);
+ msp3400c_setvolume(mspmix->bus,mspmix->left,mspmix->right);
+ UNLOCK_I2C_BUS(mspmix->bus);
+ mixer_modcnt++;
/* fall */
case MIXER_READ(SOUND_MIXER_VOLUME):
- ret = v4l_to_mix2(msp->left, msp->right);
+ ret = v4l_to_mix2(mspmix->left, mspmix->right);
break;
case MIXER_WRITE(SOUND_MIXER_BASS):
- msp->bass = mix_to_v4l(val);
- LOCK_I2C_BUS(msp->bus);
- msp3400c_setbass(msp->bus,msp->bass);
- UNLOCK_I2C_BUS(msp->bus);
+ mspmix->bass = mix_to_v4l(val);
+ LOCK_I2C_BUS(mspmix->bus);
+ msp3400c_setbass(mspmix->bus,mspmix->bass);
+ UNLOCK_I2C_BUS(mspmix->bus);
+ mixer_modcnt++;
/* fall */
case MIXER_READ(SOUND_MIXER_BASS):
- ret = v4l_to_mix(msp->bass);
+ ret = v4l_to_mix(mspmix->bass);
break;
case MIXER_WRITE(SOUND_MIXER_TREBLE):
- msp->treble = mix_to_v4l(val);
- LOCK_I2C_BUS(msp->bus);
- msp3400c_settreble(msp->bus,msp->treble);
- UNLOCK_I2C_BUS(msp->bus);
+ mspmix->treble = mix_to_v4l(val);
+ LOCK_I2C_BUS(mspmix->bus);
+ msp3400c_settreble(mspmix->bus,mspmix->treble);
+ UNLOCK_I2C_BUS(mspmix->bus);
+ mixer_modcnt++;
/* fall */
case MIXER_READ(SOUND_MIXER_TREBLE):
- ret = v4l_to_mix(msp->treble);
+ ret = v4l_to_mix(mspmix->treble);
break;
default:
+ up(&mixer_sem);
return -EINVAL;
}
+ up(&mixer_sem);
if (put_user(ret, (int *)arg))
return -EFAULT;
return 0;
}
-struct mixer_operations msp3400c_mixer = {
- "video4linux",
- "TV card sound (msp3400)",
- msp3400c_mixer_ioctl
-};
-
-static int msp3400c_mixer_init(struct msp3400c *msp)
+static int
+msp3400c_mixer_open(struct inode *inode, struct file *file)
{
- int m;
-
- msp->mixer = m = sound_alloc_mixerdev();
- if (m == -1)
- return -1;
-
- mixer_devs[m] = (struct mixer_operations *)
- kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
- if (mixer_devs[m] == NULL) {
- printk(KERN_ERR "msp3400c: can't allocate memory\n");
- sound_unload_mixerdev(m);
- return -1;
- }
- memcpy(mixer_devs[m],&msp3400c_mixer,sizeof(struct mixer_operations));
- mixer_devs[m]->devc = msp;
- return 0;
+ MOD_INC_USE_COUNT;
+ return 0;
}
-static int msp3400c_mixer_close(struct msp3400c *msp)
+static int
+msp3400c_mixer_release(struct inode *inode, struct file *file)
{
- int m = msp->mixer;
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
- if (m != -1 ) {
- sound_unload_mixerdev(m);
- kfree(mixer_devs[m]);
- }
- return 0;
+static loff_t
+msp3400c_mixer_llseek(struct file *file, loff_t offset, int origin)
+{
+ return -ESPIPE;
}
+static /*const*/ struct file_operations msp3400c_mixer_fops = {
+ &msp3400c_mixer_llseek,
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ &msp3400c_mixer_ioctl,
+ NULL, /* mmap */
+ &msp3400c_mixer_open,
+ NULL,
+ &msp3400c_mixer_release,
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL, /* lock */
+};
+
#endif
/* ----------------------------------------------------------------------- */
static int msp3400c_attach(struct i2c_device *device)
{
- unsigned long flags;
struct semaphore sem = MUTEX_LOCKED;
struct msp3400c *msp;
int rev1,rev2;
+ LOCK_FLAGS;
device->data = msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL);
if (NULL == msp)
@@ -913,17 +1036,24 @@ static int msp3400c_attach(struct i2c_device *device)
if (-1 == msp3400c_reset(msp->bus)) {
UNLOCK_I2C_BUS(msp->bus);
kfree(msp);
- return -EIO;
+ dprintk("msp3400: no chip found\n");
+ return -1;
}
+ rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
+ rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
+ if (0 == rev1 && 0 == rev2) {
+ UNLOCK_I2C_BUS(msp->bus);
+ kfree(msp);
+ printk("msp3400: error while reading chip version\n");
+ return -1;
+ }
+
msp3400c_setmode(msp, MSP_MODE_FM_TERRA);
msp3400c_setvolume(msp->bus, msp->left, msp->right);
msp3400c_setbass(msp->bus, msp->bass);
msp3400c_settreble(msp->bus, msp->treble);
- rev1 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1e);
- rev2 = msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1f);
-
#if 0
/* this will turn on a 1kHz beep - might be useful for debugging... */
msp3400c_write(msp->bus,I2C_MSP3400C_DFP, 0x0014, 0x1040);
@@ -932,7 +1062,7 @@ static int msp3400c_attach(struct i2c_device *device)
sprintf(device->name,"MSP34%02d%c-%c%d",
(rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
- msp->nicam = (((rev2>>8)&0xff) == 10) ? 1 : 0;
+ msp->nicam = (((rev2>>8)&0xff) != 00) ? 1 : 0;
/* timer for stereo checking */
msp->wake_stereo.function = msp3400c_stereo_wake;
@@ -940,19 +1070,20 @@ static int msp3400c_attach(struct i2c_device *device)
/* startup control thread */
MOD_INC_USE_COUNT;
+ msp->wq = NULL;
msp->notify = &sem;
kernel_thread(msp3400c_thread, (void *)msp, 0);
down(&sem);
msp->notify = NULL;
- if (!msp->active)
- up(msp->wait);
+ wake_up_interruptible(&msp->wq);
printk(KERN_INFO "msp3400: init: chip=%s",device->name);
if (msp->nicam)
printk(", has NICAM support");
#ifdef REGISTER_MIXER
- if (0 == msp3400c_mixer_init(msp))
- printk(", registered as sound mixer");
+ down(&mixer_sem);
+ mspmix = msp;
+ up(&mixer_sem);
#endif
printk("\n");
return 0;
@@ -960,12 +1091,14 @@ static int msp3400c_attach(struct i2c_device *device)
static int msp3400c_detach(struct i2c_device *device)
{
- unsigned long flags;
struct semaphore sem = MUTEX_LOCKED;
struct msp3400c *msp = (struct msp3400c*)device->data;
+ LOCK_FLAGS;
#ifdef REGISTER_MIXER
- msp3400c_mixer_close(msp);
+ down(&mixer_sem);
+ mspmix = NULL;
+ up(&mixer_sem);
#endif
/* shutdown control thread */
@@ -974,8 +1107,7 @@ static int msp3400c_detach(struct i2c_device *device)
{
msp->notify = &sem;
msp->rmmod = 1;
- if (!msp->active)
- up(msp->wait);
+ wake_up_interruptible(&msp->wq);
down(&sem);
msp->notify = NULL;
}
@@ -992,9 +1124,10 @@ static int msp3400c_detach(struct i2c_device *device)
static int msp3400c_command(struct i2c_device *device,
unsigned int cmd, void *arg)
{
- unsigned long flags;
struct msp3400c *msp = (struct msp3400c*)device->data;
int *iarg = (int*)arg;
+ __u16 *sarg = arg;
+ LOCK_FLAGS;
switch (cmd) {
case MSP_SET_RADIO:
@@ -1004,74 +1137,79 @@ static int msp3400c_command(struct i2c_device *device,
LOCK_I2C_BUS(msp->bus);
msp3400c_setmode(msp,MSP_MODE_FM_RADIO);
msp3400c_setcarrier(msp->bus, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
+ msp3400c_setvolume(msp->bus,msp->left, msp->right);
UNLOCK_I2C_BUS(msp->bus);
break;
case MSP_SET_TVNORM:
msp->norm = *iarg;
break;
+ case MSP_SWITCH_MUTE:
+ /* channels switching step one -- mute */
+ msp->watch_stereo=0;
+ del_timer(&msp->wake_stereo);
+ LOCK_I2C_BUS(msp->bus);
+ msp3400c_setvolume(msp->bus,0,0);
+ UNLOCK_I2C_BUS(msp->bus);
+ break;
case MSP_NEWCHANNEL:
+ /* channels switching step two -- trigger sound carrier scan */
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
- if (!msp->active)
- up(msp->wait);
- else
+ if (msp->active)
msp->restart = 1;
+ wake_up_interruptible(&msp->wq);
break;
case MSP_GET_VOLUME:
- *iarg = (msp->left > msp->right) ? msp->left : msp->right;
+ *sarg = (msp->left > msp->right) ? msp->left : msp->right;
break;
case MSP_SET_VOLUME:
- msp->left = msp->right = *iarg;
+ msp->left = msp->right = *sarg;
LOCK_I2C_BUS(msp->bus);
msp3400c_setvolume(msp->bus,msp->left, msp->right);
UNLOCK_I2C_BUS(msp->bus);
break;
case MSP_GET_BASS:
- *iarg = msp->bass;
+ *sarg = msp->bass;
break;
case MSP_SET_BASS:
- msp->bass = *iarg;
+ msp->bass = *sarg;
LOCK_I2C_BUS(msp->bus);
msp3400c_setbass(msp->bus,msp->bass);
UNLOCK_I2C_BUS(msp->bus);
break;
case MSP_GET_TREBLE:
- *iarg = msp->treble;
+ *sarg = msp->treble;
break;
case MSP_SET_TREBLE:
- msp->treble = *iarg;
+ msp->treble = *sarg;
LOCK_I2C_BUS(msp->bus);
msp3400c_settreble(msp->bus,msp->treble);
UNLOCK_I2C_BUS(msp->bus);
break;
case MSP_GET_STEREO:
- *iarg = msp->stereo;
+ *sarg = msp->stereo;
break;
case MSP_SET_STEREO:
- if (*iarg) {
+ if (*sarg) {
msp->watch_stereo=0;
del_timer(&msp->wake_stereo);
LOCK_I2C_BUS(msp->bus);
- msp3400c_setstereo(msp,*iarg);
+ msp3400c_setstereo(msp,*sarg);
UNLOCK_I2C_BUS(msp->bus);
}
break;
case MSP_GET_DC:
LOCK_I2C_BUS(msp->bus);
- *iarg = (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
- (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c);
+ *sarg = ((int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1b) +
+ (int)msp3400c_read(msp->bus, I2C_MSP3400C_DFP, 0x1c));
UNLOCK_I2C_BUS(msp->bus);
break;
-
- case MSP_GET_UNIT:
- *iarg = msp->mixer;
- break;
-
+
default:
return -EINVAL;
}
@@ -1090,8 +1228,6 @@ struct i2c_driver i2c_driver_msp = {
msp3400c_command
};
-EXPORT_NO_SYMBOLS;
-
#ifdef MODULE
int init_module(void)
#else
@@ -1099,6 +1235,10 @@ int init_module(void)
#endif
{
i2c_register_driver(&i2c_driver_msp);
+#ifdef REGISTER_MIXER
+ if ((mixer_num = register_sound_mixer(&msp3400c_mixer_fops, -1)) < 0)
+ printk(KERN_ERR "msp3400c: cannot allocate mixer device\n");
+#endif
return 0;
}
@@ -1106,6 +1246,10 @@ int init_module(void)
void cleanup_module(void)
{
i2c_unregister_driver(&i2c_driver_msp);
+#ifdef REGISTER_MIXER
+ if (mixer_num >= 0)
+ unregister_sound_mixer(mixer_num);
+#endif
}
#endif
diff --git a/drivers/char/msp3400.h b/drivers/char/msp3400.h
index 8b093ff05..7f0ba30e5 100644
--- a/drivers/char/msp3400.h
+++ b/drivers/char/msp3400.h
@@ -7,19 +7,19 @@
#define MSP_SET_RADIO _IO('m',2) /* Radio mode */
#define MSP_NEWCHANNEL _IO('m',3) /* indicate new channel */
-#define MSP_GET_VOLUME _IOR('m',4,int)
-#define MSP_SET_VOLUME _IOW('m',5,int)
+#define MSP_GET_VOLUME _IOR('m',4,__u16)
+#define MSP_SET_VOLUME _IOW('m',5,__u16)
-#define MSP_GET_STEREO _IOR('m',6,int)
-#define MSP_SET_STEREO _IOW('m',7,int)
+#define MSP_GET_STEREO _IOR('m',6,__u16)
+#define MSP_SET_STEREO _IOW('m',7,__u16)
-#define MSP_GET_DC _IOW('m',8,int)
+#define MSP_GET_DC _IOW('m',8,__u16)
-#define MSP_GET_BASS _IOR('m', 9,int)
-#define MSP_SET_BASS _IOW('m',10,int)
-#define MSP_GET_TREBLE _IOR('m',11,int)
-#define MSP_SET_TREBLE _IOW('m',12,int)
-
-#define MSP_GET_UNIT _IOR('m',13,int)
+#define MSP_GET_BASS _IOR('m', 9,__u16)
+#define MSP_SET_BASS _IOW('m',10,__u16)
+#define MSP_GET_TREBLE _IOR('m',11,__u16)
+#define MSP_SET_TREBLE _IOW('m',12,__u16)
+#define MSP_GET_UNIT _IOR('m',13,int)
+#define MSP_SWITCH_MUTE _IO('m',14)
#endif /* MSP3400_H */
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 5456640cb..4bf35716b 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -73,7 +73,8 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
*/
static void check_unthrottle(struct tty_struct * tty)
{
- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+ if (tty->count &&
+ test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver.unthrottle)
tty->driver.unthrottle(tty);
}
@@ -921,17 +922,21 @@ do_it_again:
}
}
- add_wait_queue(&tty->read_wait, &wait);
+ if (down_interruptible(&tty->atomic_read))
+ return -ERESTARTSYS;
- disable_bh(TQUEUE_BH);
+ add_wait_queue(&tty->read_wait, &wait);
+ set_bit(TTY_DONT_FLIP, &tty->flags);
while (nr) {
/* First test for status change. */
if (tty->packet && tty->link->ctrl_status) {
+ unsigned char cs;
if (b != buf)
break;
- put_user(tty->link->ctrl_status, b++);
- nr--;
+ cs = tty->link->ctrl_status;
tty->link->ctrl_status = 0;
+ put_user(cs, b++);
+ nr--;
break;
}
/* This statement must be first before checking for input
@@ -960,9 +965,9 @@ do_it_again:
retval = -ERESTARTSYS;
break;
}
- enable_bh(TQUEUE_BH);
+ clear_bit(TTY_DONT_FLIP, &tty->flags);
timeout = schedule_timeout(timeout);
- disable_bh(TQUEUE_BH);
+ set_bit(TTY_DONT_FLIP, &tty->flags);
continue;
}
current->state = TASK_RUNNING;
@@ -1024,7 +1029,8 @@ do_it_again:
if (time)
timeout = time;
}
- enable_bh(TQUEUE_BH);
+ clear_bit(TTY_DONT_FLIP, &tty->flags);
+ up(&tty->atomic_read);
remove_wait_queue(&tty->read_wait, &wait);
if (!waitqueue_active(&tty->read_wait))
diff --git a/drivers/char/pc_keyb.c b/drivers/char/pc_keyb.c
index a795cf21c..f4a4d51f3 100644
--- a/drivers/char/pc_keyb.c
+++ b/drivers/char/pc_keyb.c
@@ -56,6 +56,7 @@ static void kbd_write_command_w(int data);
static void kbd_write_output_w(int data);
spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
/* used only by send_data - set by keyboard_interrupt */
static volatile unsigned char reply_expected = 0;
@@ -80,7 +81,7 @@ static int aux_count = 0;
#endif /* CONFIG_PSMOUSE */
/*
- * Wait for keyboard controller input buffer is empty.
+ * Wait for keyboard controller input buffer to drain.
*
* Don't use 'jiffies' so that we don't depend on
* interrupts..
@@ -98,17 +99,13 @@ static inline void kb_wait(void)
unsigned char status;
do {
- status = kbd_read_status();
- kbd_pause();
- if (status & KBD_STAT_OBF) {
- if (status & KBD_STAT_MOUSE_OBF)
- kbd_read_input(); /* Flush */
- kbd_pause();
- }
+ /*
+ * "handle_kbd_event()" will handle any incoming events
+ * while we wait - keypresses or mouse movement.
+ */
+ unsigned char status = handle_kbd_event();
- status = kbd_read_status();
- kbd_pause();
- if (!(status & KBD_STAT_IBF))
+ if (! (status & KBD_STAT_IBF))
return;
mdelay(1);
timeout--;
@@ -254,20 +251,6 @@ int pckbd_getkeycode(unsigned int scancode)
e0_keys[scancode - 128];
}
-#if DISABLE_KBD_DURING_INTERRUPTS
-static inline void send_cmd(unsigned char c)
-{
- kb_wait();
- kbd_write_command(c);
-}
-
-#define disable_keyboard() send_cmd(KBD_CCMD_KBD_DISABLE)
-#define enable_keyboard() send_cmd(KBD_CCMD_KBD_ENABLE)
-#else
-#define disable_keyboard() /* nothing */
-#define enable_keyboard() /* nothing */
-#endif
-
static int do_acknowledge(unsigned char scancode)
{
if (reply_expected) {
@@ -412,16 +395,17 @@ char pckbd_unexpected_up(unsigned char keycode)
return 0200;
}
-void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ * It requires that we hold the keyboard controller
+ * spinlock.
+ */
+static unsigned char handle_kbd_event(void)
{
- unsigned long flags;
- unsigned char status;
-
- spin_lock_irqsave(&kbd_controller_lock, flags);
- disable_keyboard();
- kbd_pt_regs = regs;
+ unsigned char status = kbd_read_status();
- status = kbd_read_status();
while (status & KBD_STAT_OBF) {
unsigned char scancode;
@@ -452,7 +436,17 @@ void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
status = kbd_read_status();
}
- enable_keyboard();
+ return status;
+}
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ kbd_pt_regs = regs;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+ handle_kbd_event();
spin_unlock_irqrestore(&kbd_controller_lock, flags);
}
@@ -718,6 +712,52 @@ void __init pckbd_init_hw(void)
}
#if defined CONFIG_PSMOUSE
+
+/*
+ * Check if this is a dual port controller.
+ */
+static int __init detect_auxiliary_port(void)
+{
+ unsigned long flags;
+ unsigned char status;
+ unsigned char val;
+ int loops = 5;
+ int retval = 0;
+
+ spin_lock_irqsave(&kbd_controller_lock, flags);
+
+ /* Put the value 0x5A in the output buffer using the "Write
+ * Auxiliary Device Output Buffer" command (0xD3). Poll the
+ * Status Register for a while to see if the value really
+ * turns up in the Data Register. If the KBD_STAT_MOUSE_OBF
+ * bit is also set to 1 in the Status Register, we assume this
+ * controller has an Auxiliary Port (a.k.a. Mouse Port).
+ */
+ kb_wait();
+ kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
+
+ kb_wait();
+ kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
+
+ status = kbd_read_status();
+ while (!(status & KBD_STAT_OBF) && loops--) {
+ mdelay(1);
+ status = kbd_read_status();
+ }
+
+ if (status & KBD_STAT_OBF) {
+ val = kbd_read_input();
+ if (val == 0x5a && (status & KBD_STAT_MOUSE_OBF)) {
+ printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
+ retval = 1;
+ }
+ }
+
+ spin_unlock_irqrestore(&kbd_controller_lock, flags);
+
+ return retval;
+}
+
/*
* Send a byte to the mouse.
*/
@@ -763,6 +803,11 @@ static int fasync_aux(int fd, struct file *filp, int on)
}
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
static int release_aux(struct inode * inode, struct file * file)
{
fasync_aux(-1, file, 0);
@@ -898,18 +943,9 @@ static struct miscdevice psaux_mouse = {
static int __init psaux_init(void)
{
-#if 0
- /*
- * Don't bother with the BIOS flag: even if we don't have
- * a mouse connected at bootup we may still want to connect
- * one later, and we don't want to just let the BIOS tell
- * us that it has no mouse..
- */
- if (aux_device_present != 0xaa)
+ if (!detect_auxiliary_port())
return -EIO;
- printk(KERN_INFO "PS/2 auxiliary pointing device detected -- driver installed.\n");
-#endif
misc_register(&psaux_mouse);
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
memset(queue, 0, sizeof(*queue));
diff --git a/drivers/char/pcxx.c b/drivers/char/pcxx.c
index b1c1bb3e3..26b1033c3 100644
--- a/drivers/char/pcxx.c
+++ b/drivers/char/pcxx.c
@@ -70,6 +70,7 @@
#include <linux/malloc.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/version.h>
#ifndef MODULE
#include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
diff --git a/drivers/char/pms.c b/drivers/char/pms.c
index 8886b59be..252929f82 100644
--- a/drivers/char/pms.c
+++ b/drivers/char/pms.c
@@ -221,7 +221,7 @@ static void pms_colour(short colour)
pms_i2c_write(0x8A, 0x00, colour);
break;
case PHILIPS1:
- pms_i2c_write(0x42, 012, colour);
+ pms_i2c_write(0x42, 0x12, colour);
break;
}
}
diff --git a/drivers/char/radio-aimslab.c b/drivers/char/radio-aimslab.c
index 59d95042e..97d13882f 100644
--- a/drivers/char/radio-aimslab.c
+++ b/drivers/char/radio-aimslab.c
@@ -101,6 +101,7 @@ static int rt_setvol(struct rt_device *dev, int vol)
outb(0x48, io); /* volume down but still "on" */
sleep_delay(2000000); /* make sure it's totally down */
outb(0xd0, io); /* volume steady, off */
+ dev->curvol = 0; /* track the volume state! */
return 0;
}
diff --git a/drivers/char/radio-gemtek.c b/drivers/char/radio-gemtek.c
new file mode 100644
index 000000000..1bfe30e30
--- /dev/null
+++ b/drivers/char/radio-gemtek.c
@@ -0,0 +1,310 @@
+/* GemTek radio card driver for Linux (C) 1998 Jonas Munsin <jmunsin@iki.fi>
+ *
+ * GemTek hasn't released any specs on the card, so the protocol had to
+ * be reverse engineered with dosemu.
+ *
+ * Besides the protocol changes, this is mostly a copy of:
+ *
+ * RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
+ *
+ * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
+ * Coverted to new API by Alan Cox <Alan.Cox@linux.org>
+ * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
+ *
+ * TODO: Allow for more than one of these foolish entities :-)
+ *
+ */
+
+#include <linux/module.h> /* Modules */
+#include <linux/init.h> /* Initdata */
+#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/delay.h> /* udelay */
+#include <asm/io.h> /* outb, outb_p */
+#include <asm/uaccess.h> /* copy to/from user */
+#include <linux/videodev.h> /* kernel radio structs */
+#include <linux/config.h> /* CONFIG_RADIO_GEMTEK_PORT */
+
+#ifndef CONFIG_RADIO_GEMTEK_PORT
+#define CONFIG_RADIO_GEMTEK_PORT -1
+#endif
+
+static int io = CONFIG_RADIO_GEMTEK_PORT;
+static int users = 0;
+
+struct gemtek_device
+{
+ int port;
+ unsigned long curfreq;
+ int muted;
+};
+
+
+/* local things */
+
+/* the correct way to mute the gemtek may be to write the last written
+ * frequency || 0x10, but just writing 0x10 once seems to do it as well
+ */
+static void gemtek_mute(struct gemtek_device *dev)
+{
+ if(dev->muted)
+ return;
+ outb(0x10, io);
+ dev->muted = 1;
+}
+
+static void gemtek_unmute(struct gemtek_device *dev)
+{
+ if(dev->muted == 0)
+ return;
+ outb(0x20, io);
+ dev->muted = 0;
+}
+
+static void zero(void)
+{
+ outb_p(0x04, io);
+ udelay(5);
+ outb_p(0x05, io);
+ udelay(5);
+}
+
+static void one(void)
+{
+ outb_p(0x06, io);
+ udelay(5);
+ outb_p(0x07, io);
+ udelay(5);
+}
+
+static int gemtek_setfreq(struct gemtek_device *dev, unsigned long freq)
+{
+ int i;
+
+/* freq = 78.25*((float)freq/16000.0 + 10.52); */
+
+ freq /= 16;
+ freq += 10520;
+ freq *= 7825;
+ freq /= 100000;
+
+ /* 2 start bits */
+ outb_p(0x03, io);
+ udelay(5);
+ outb_p(0x07, io);
+ udelay(5);
+
+ /* 28 frequency bits (lsb first) */
+ for (i = 0; i < 14; i++)
+ if (freq & (1 << i))
+ one();
+ else
+ zero();
+ /* 36 unknown bits */
+ for (i = 0; i < 11; i++)
+ zero();
+ one();
+ for (i = 0; i < 4; i++)
+ zero();
+ one();
+ zero();
+
+ /* 2 end bits */
+ outb_p(0x03, io);
+ udelay(5);
+ outb_p(0x07, io);
+ udelay(5);
+
+ return 0;
+}
+
+int gemtek_getsigstr(struct gemtek_device *dev)
+{
+ inb(io);
+ udelay(5);
+ if (inb(io) & 8) /* bit set = no signal present */
+ return 0;
+ return 1; /* signal present */
+}
+
+static int gemtek_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+ struct gemtek_device *rt=dev->priv;
+
+ switch(cmd)
+ {
+ case VIDIOCGCAP:
+ {
+ struct video_capability v;
+ v.type=VID_TYPE_TUNER;
+ v.channels=1;
+ v.audios=1;
+ /* No we don't do pictures */
+ v.maxwidth=0;
+ v.maxheight=0;
+ v.minwidth=0;
+ v.minheight=0;
+ strcpy(v.name, "GemTek");
+ if(copy_to_user(arg,&v,sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCGTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg,sizeof(v))!=0)
+ return -EFAULT;
+ if(v.tuner) /* Only 1 tuner */
+ return -EINVAL;
+ v.rangelow=87*16000;
+ v.rangehigh=108*16000;
+ v.flags=VIDEO_TUNER_LOW;
+ v.mode=VIDEO_MODE_AUTO;
+ v.signal=0xFFFF*gemtek_getsigstr(rt);
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSTUNER:
+ {
+ struct video_tuner v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.tuner!=0)
+ return -EINVAL;
+ /* Only 1 tuner so no setting needed ! */
+ return 0;
+ }
+ case VIDIOCGFREQ:
+ if(copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq)))
+ return -EFAULT;
+ return 0;
+ case VIDIOCSFREQ:
+ if(copy_from_user(&rt->curfreq, arg,sizeof(rt->curfreq)))
+ return -EFAULT;
+ /* needs to be called twice in order for getsigstr to work */
+ gemtek_setfreq(rt, rt->curfreq);
+ gemtek_setfreq(rt, rt->curfreq);
+ return 0;
+ case VIDIOCGAUDIO:
+ {
+ struct video_audio v;
+ memset(&v,0, sizeof(v));
+ v.flags|=VIDEO_AUDIO_MUTABLE;
+ v.volume=1;
+ v.step=65535;
+ strcpy(v.name, "Radio");
+ if(copy_to_user(arg,&v, sizeof(v)))
+ return -EFAULT;
+ return 0;
+ }
+ case VIDIOCSAUDIO:
+ {
+ struct video_audio v;
+ if(copy_from_user(&v, arg, sizeof(v)))
+ return -EFAULT;
+ if(v.audio)
+ return -EINVAL;
+
+ if(v.flags&VIDEO_AUDIO_MUTE)
+ gemtek_mute(rt);
+ else
+ gemtek_unmute(rt);
+
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+static int gemtek_open(struct video_device *dev, int flags)
+{
+ if(users)
+ return -EBUSY;
+ users++;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static void gemtek_close(struct video_device *dev)
+{
+ users--;
+ MOD_DEC_USE_COUNT;
+}
+
+static struct gemtek_device gemtek_unit;
+
+static struct video_device gemtek_radio=
+{
+ "GemTek radio",
+ VID_TYPE_TUNER,
+ VID_HARDWARE_GEMTEK,
+ gemtek_open,
+ gemtek_close,
+ NULL, /* Can't read (no capture ability) */
+ NULL, /* Can't write */
+ NULL, /* Can't poll */
+ gemtek_ioctl,
+ NULL,
+ NULL
+};
+
+__initfunc(int gemtek_init(struct video_init *v))
+{
+ if (check_region(io, 4))
+ {
+ printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
+ return -EBUSY;
+ }
+
+ gemtek_radio.priv=&gemtek_unit;
+
+ if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO)==-1)
+ return -EINVAL;
+
+ request_region(io, 4, "gemtek");
+ printk(KERN_INFO "GemTek Radio Card driver.\n");
+
+ /* mute card - prevents noisy bootups */
+ outb(0x10, io);
+ udelay(5);
+ gemtek_unit.muted = 1;
+
+ /* this is _maybe_ unnecessary */
+ outb(0x01, io);
+
+ return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Jonas Munsin");
+MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c)");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+ if(io==-1)
+ {
+ printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c\n");
+ return -EINVAL;
+ }
+ return gemtek_init(NULL);
+}
+
+void cleanup_module(void)
+{
+ video_unregister_device(&gemtek_radio);
+ release_region(io,4);
+}
+
+#endif
+
+/*
+ Local variables:
+ compile-command: "gcc -c -DMODVERSIONS -D__KERNEL__ -DMODULE -O6 -Wall -Wstrict-prototypes -I /home/blp/tmp/linux-2.1.111-rtrack/include radio-rtrack2.c"
+ End:
+*/
diff --git a/drivers/char/radio-zoltrix.c b/drivers/char/radio-zoltrix.c
index 115606ac3..80a72d4b4 100644
--- a/drivers/char/radio-zoltrix.c
+++ b/drivers/char/radio-zoltrix.c
@@ -12,6 +12,15 @@
* to get fine volume control over the low volume range.
*
* Some code derived from code by Frans Brinkman
+ *
+ * 1999-01-05 - (C. van Schaik)
+ * - Changed tuning to 1/160Mhz accuracy
+ * - Added stereo support
+ * (card defaults to stereo)
+ * (can explicitly force mono on the card)
+ * (can detect if station is in stereo)
+ * - Added unmute function
+ * - Reworked ioctl functions
*/
#include <linux/module.h> /* Modules */
@@ -35,6 +44,7 @@ struct zol_device {
int curvol;
unsigned long curfreq;
int muted;
+ unsigned int stereo;
};
@@ -54,61 +64,63 @@ static void sleep_delay(long n)
}
}
+static int zol_setvol(struct zol_device *dev, int vol)
+{
+ dev->curvol = vol;
+ if (dev->muted)
+ return 0;
+
+ if (vol == 0) {
+ outb(0, io);
+ outb(0, io);
+ inb(io + 3); /* Zoltrix needs to be read to confirm */
+ return 0;
+ }
+
+ outb(dev->curvol-1, io);
+ sleep_delay(10000);
+ inb(io + 2);
+
+ return 0;
+}
+
static void zol_mute(struct zol_device *dev)
{
dev->muted = 1;
outb(0, io);
outb(0, io);
- inb(io + 3); /* Zoltrix needs to be read to confirm */
-}
-
-static void zol_on(int vol)
-{
- int l;
- outb(vol, io);
- sleep_delay(10000);
- l = inb(io + 2);
+ inb(io + 3); /* Zoltrix needs to be read to confirm */
}
-static int zol_setvol(struct zol_device *dev, int vol)
+static void zol_unmute(struct zol_device *dev)
{
- if (vol == dev->curvol) { /* requested volume = current */
- if (dev->muted) { /* user is unmuting the card */
- dev->muted = 0;
- zol_on(vol);
- }
- return 0;
- }
- if (vol == 0) { /* volume = 0 means mute the card */
- zol_mute(dev);
- return 0;
- }
dev->muted = 0;
- dev->curvol = vol;
-
- zol_on(vol);
-
- return 0;
+ zol_setvol(dev, dev->curvol);
}
static int zol_setfreq(struct zol_device *dev, unsigned long freq)
{
/* tunes the radio to the desired frequency */
unsigned long long bitmask, f, m;
+ unsigned int stereo = dev->stereo;
int i;
- m = (freq * 25 / 4 - 8800) * 2;
+ if (freq == 0)
+ return 1;
+ m = (freq / 160 - 8800) * 2;
f = (unsigned long long) m + 0x4d1c;
bitmask = 0xc480402c10080000ull;
i = 45;
- zol_mute(dev);
+ outb(0, io);
+ outb(0, io);
+ inb(io + 3); /* Zoltrix needs to be read to confirm */
outb(0x40, io);
outb(0xc0, io);
- bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( /*stereo */ 0 << 31));
+ bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31));
while (i--) {
if ((bitmask & 0x8000000000000000ull) != 0) {
outb(0x80, io);
@@ -131,7 +143,18 @@ static int zol_setfreq(struct zol_device *dev, unsigned long freq)
outb(0x80, io);
outb(0xc0, io);
outb(0x40, io);
- zol_on(dev->curvol);
+ sleep_delay(1000);
+ inb(io+2);
+
+ sleep_delay(1000);
+ if (dev->muted)
+ {
+ outb(0, io);
+ outb(0, io);
+ inb(io + 3);
+ sleep_delay(1000);
+ } else
+ zol_setvol(dev, dev->curvol);
return 0;
}
@@ -149,27 +172,42 @@ int zol_getsigstr(struct zol_device *dev)
sleep_delay(1000);
b = inb(io);
- if ((a == b) && (a == 0xdf)) /* I found this out by playing */
- /* with a binary scanner on the card io */
- return (1);
- else
+ if (a != b)
return (0);
- if (inb(io) & 2) /* bit set = no signal present */
- return 0;
- return 1; /* signal present */
+ if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */
+ || (a == 0xef)) /* with a binary scanner on the card io */
+ return (1);
+ return (0);
+}
+
+int zol_is_stereo (struct zol_device *dev)
+{
+ int x1, x2;
+
+ outb(0x00, io);
+ outb(dev->curvol, io);
+ sleep_delay(20000);
+
+ x1 = inb(io);
+ sleep_delay(1000);
+ x2 = inb(io);
+
+ if ((x1 == x2) && (x1 == 0xcf))
+ return 1;
+ return 0;
}
static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
- struct zol_device *rt = dev->priv;
+ struct zol_device *zol = dev->priv;
switch (cmd) {
case VIDIOCGCAP:
{
struct video_capability v;
v.type = VID_TYPE_TUNER;
- v.channels = 1;
+ v.channels = 1 + zol->stereo;
v.audios = 1;
/* No we don't do pictures */
v.maxwidth = 0;
@@ -184,15 +222,21 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
case VIDIOCGTUNER:
{
struct video_tuner v;
- if (copy_from_user(&v, arg, sizeof(v)) != 0)
+/*
+ if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
- if (v.tuner) /* Only 1 tuner */
+ if (v.tuner)
return -EINVAL;
- v.rangelow = (int) (88.0 * 16);
- v.rangehigh = (int) (108.0 * 16);
- v.flags = 0;
+*/
+ v.tuner = 0;
+ strcpy(v.name, "Zoltrix Radio");
+ v.rangelow = (int) (88.0 * 16000);
+ v.rangehigh = (int) (108.0 * 16000);
+ v.flags = zol_is_stereo(zol)
+ ? VIDEO_TUNER_STEREO_ON : 0;
+ v.flags |= VIDEO_TUNER_LOW;
v.mode = VIDEO_MODE_AUTO;
- v.signal = 0xFFFF * zol_getsigstr(rt);
+ v.signal = 0xFFFF * zol_getsigstr(zol);
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
return 0;
@@ -208,22 +252,24 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return 0;
}
case VIDIOCGFREQ:
- if (copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq)))
+ if (copy_to_user(arg, &zol->curfreq, sizeof(zol->curfreq)))
return -EFAULT;
return 0;
case VIDIOCSFREQ:
- if (copy_from_user(&rt->curfreq, arg, sizeof(rt->curfreq)))
+ if (copy_from_user(&zol->curfreq, arg, sizeof(zol->curfreq)))
return -EFAULT;
- zol_setfreq(rt, rt->curfreq);
+ zol_setfreq(zol, zol->curfreq);
return 0;
case VIDIOCGAUDIO:
{
struct video_audio v;
memset(&v, 0, sizeof(v));
v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
- v.volume = rt->curvol * 4096;
+ v.mode != zol_is_stereo(zol)
+ ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+ v.volume = zol->curvol * 4096;
v.step = 4096;
- strcpy(v.name, "Radio");
+ strcpy(v.name, "Zoltrix Radio");
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
return 0;
@@ -237,9 +283,23 @@ static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
return -EINVAL;
if (v.flags & VIDEO_AUDIO_MUTE)
- zol_mute(rt);
+ zol_mute(zol);
else
- zol_setvol(rt, v.volume / 4096);
+ zol_unmute(zol);
+
+ if (v.flags & VIDEO_AUDIO_VOLUME)
+ zol_setvol(zol, v.volume / 4096);
+
+ if (v.mode & VIDEO_SOUND_STEREO)
+ {
+ zol->stereo = 1;
+ zol_setfreq(zol, zol->curfreq);
+ }
+ if (v.mode & VIDEO_SOUND_MONO)
+ {
+ zol->stereo = 0;
+ zol_setfreq(zol, zol->curfreq);
+ }
return 0;
}
@@ -286,6 +346,10 @@ __initfunc(int zoltrix_init(struct video_init *v))
printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
return -EBUSY;
}
+ if ((io != 0x20c) && (io != 0x30c)) {
+ printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n");
+ return -ENXIO;
+ }
zoltrix_radio.priv = &zoltrix_unit;
if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1)
@@ -304,6 +368,7 @@ __initfunc(int zoltrix_init(struct video_init *v))
inb(io + 3);
zoltrix_unit.curvol = 0;
+ zoltrix_unit.stereo = 1;
return 0;
}
diff --git a/drivers/char/random.c b/drivers/char/random.c
index c980d5192..f78974d69 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -232,6 +232,11 @@
* Eastlake, Steve Crocker, and Jeff Schiller.
*/
+/*
+ * Added a check for signal pending in the extract_entropy() loop to allow
+ * the read(2) syscall to be interrupted. Copyright (C) 1998 Andrea Arcangeli
+ */
+
#include <linux/utsname.h>
#include <linux/config.h>
#include <linux/kernel.h>
@@ -1269,7 +1274,14 @@ static ssize_t extract_entropy(struct random_bucket *r, char * buf,
buf += i;
add_timer_randomness(r, &extract_timer_state, nbytes);
if (to_user && current->need_resched)
+ {
+ if (signal_pending(current))
+ {
+ ret = -EINTR;
+ break;
+ }
schedule();
+ }
}
/* Wipe data just returned from memory */
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 7da0fa512..7764997b5 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -228,7 +228,7 @@ extern inline void rc_long_delay(unsigned long delay)
{
unsigned long i;
- for (i = jiffies + delay; i > jiffies; ) ;
+ for (i = jiffies + delay; time_after(i,jiffies); ) ;
}
/* Reset and setup CD180 chip */
@@ -1172,8 +1172,8 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
timeout = jiffies+HZ;
while(port->IER & IER_TXEMPTY) {
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(port->timeout);
- if (jiffies > timeout)
+ schedule_timeout(port->timeout);
+ if (time_after(jiffies, timeout))
break;
}
}
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 6a26bb088..5fde4639e 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -94,7 +94,7 @@ void mask_rtc_irq_bit(unsigned char bit);
static inline unsigned char rtc_is_updating(void);
/*
- * Bits in rtc_status. (7 bits of room for future expansion)
+ * Bits in rtc_status. (6 bits of room for future expansion)
*/
#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
diff --git a/drivers/char/saa5249.c b/drivers/char/saa5249.c
index bc49cb80b..2e93553c5 100644
--- a/drivers/char/saa5249.c
+++ b/drivers/char/saa5249.c
@@ -460,7 +460,7 @@ static int saa5249_ioctl(struct video_device *vd, unsigned int cmd, void *arg)
if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) && /* check FOUND-bit */
(memcmp(infobits, t->vdau[req.pgbuf].laststat, sizeof(infobits)) ||
- jiffies >= t->vdau[req.pgbuf].expire))
+ time_after_eq(jiffies, t->vdau[req.pgbuf].expire)))
{ /* check if new page arrived */
if (i2c_senddata(t, CCTWR, 8, 0, 0, 0, -1) ||
i2c_getdata(t, CCTRD, VTX_PAGESIZE, t->vdau[req.pgbuf].pgbuf, FALSE))
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index e352813cc..08fa90aa5 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -156,7 +156,7 @@
#endif
static char *serial_name = "Serial driver";
-static char *serial_version = "4.26";
+static char *serial_version = "4.27";
static DECLARE_TASK_QUEUE(tq_serial);
@@ -182,7 +182,7 @@ static struct console sercons;
static unsigned detect_uart_irq (struct serial_state * state);
static void autoconfig(struct serial_state * info);
-static void change_speed(struct async_struct *info);
+static void change_speed(struct async_struct *info, struct termios *old);
static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
/*
@@ -196,7 +196,7 @@ static struct serial_uart_config uart_config[] = {
{ "16550", 1, 0 },
{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
{ "cirrus", 1, 0 },
- { "ST16650", 1, UART_CLEAR_FIFO |UART_STARTECH },
+ { "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
UART_STARTECH },
{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
@@ -1132,7 +1132,7 @@ static int startup(struct async_struct * info)
/*
* and set the speed of the serial port
*/
- change_speed(info);
+ change_speed(info, 0);
info->flags |= ASYNC_INITIALIZED;
restore_flags(flags);
@@ -1255,7 +1255,8 @@ static void shutdown(struct async_struct * info)
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static void change_speed(struct async_struct *info)
+static void change_speed(struct async_struct *info,
+ struct termios *old_termios)
{
unsigned short port;
int quot = 0, baud_base, baud;
@@ -1306,7 +1307,25 @@ static void change_speed(struct async_struct *info)
else if (baud)
quot = baud_base / baud;
}
- /* If the quotient is ever zero, default to 9600 bps */
+ /* If the quotient is zero refuse the change */
+ if (!quot && old_termios) {
+ info->tty->termios->c_cflag &= ~CBAUD;
+ info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+ baud = tty_get_baud_rate(info->tty);
+ if (!baud)
+ baud = 9600;
+ if (baud == 38400 &&
+ ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+ quot = info->state->custom_divisor;
+ else {
+ if (baud == 134)
+ /* Special case since 134 is really 134.5 */
+ quot = (2*baud_base / 269);
+ else if (baud)
+ quot = baud_base / baud;
+ }
+ }
+ /* As a last resort, if the quotient is zero, default to 9600 bps */
if (!quot)
quot = baud_base / 9600;
info->quot = quot;
@@ -1675,8 +1694,8 @@ static int set_serial_info(struct async_struct * info,
return -EPERM;
state->flags = ((state->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
- info->flags = ((state->flags & ~ASYNC_USR_MASK) |
- (info->flags & ASYNC_USR_MASK));
+ info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
state->custom_divisor = new_serial.custom_divisor;
goto check_and_exit;
}
@@ -1684,7 +1703,7 @@ static int set_serial_info(struct async_struct * info,
new_serial.irq = irq_cannonicalize(new_serial.irq);
if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
- (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) ||
+ (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) ||
(new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
(new_serial.type == PORT_STARTECH)) {
return -EINVAL;
@@ -1755,7 +1774,7 @@ check_and_exit:
info->tty->alt_speed = 230400;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
info->tty->alt_speed = 460800;
- change_speed(info);
+ change_speed(info, 0);
}
} else
retval = startup(info);
@@ -2025,7 +2044,6 @@ static int set_multiport_struct(struct async_struct * info,
"driver!!\n");
}
}
-
return 0;
}
#endif
@@ -2172,7 +2190,7 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
== RELEVANT_IFLAG(old_termios->c_iflag)))
return;
- change_speed(info);
+ change_speed(info, old_termios);
/* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) &&
@@ -2360,6 +2378,17 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
char_time = 1;
if (timeout)
char_time = MIN(char_time, timeout);
+ /*
+ * If the transmitter hasn't cleared in twice the approximate
+ * amount of time to send the entire FIFO, it probably won't
+ * ever clear. This assumes the UART isn't doing flow
+ * control, which is currently the case. Hence, if it ever
+ * takes longer than info->timeout, this is probably due to a
+ * UART bug of some kind. So, we clamp the timeout parameter at
+ * 2*info->timeout.
+ */
+ if (!timeout || timeout > 2*info->timeout)
+ timeout = 2*info->timeout;
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
printk("jiff=%lu...", jiffies);
@@ -2373,7 +2402,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
schedule_timeout(char_time);
if (signal_pending(current))
break;
- if (timeout && ((orig_jiffies + timeout) < jiffies))
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
current->state = TASK_RUNNING;
@@ -2667,13 +2696,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
*tty->termios = info->state->normal_termios;
else
*tty->termios = info->state->callout_termios;
- change_speed(info);
+ change_speed(info, 0);
}
#ifdef CONFIG_SERIAL_CONSOLE
if (sercons.cflag && sercons.index == line) {
tty->termios->c_cflag = sercons.cflag;
sercons.cflag = 0;
- change_speed(info);
+ change_speed(info, 0);
}
#endif
info->session = current->session;
@@ -2903,8 +2932,8 @@ static unsigned detect_uart_irq (struct serial_state * state)
* 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.
+ * whether or not this UART is a 16550A, since this will determine
+ * whether or not we can use its FIFO features.
*/
static void autoconfig(struct serial_state * state)
{
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 72d1f6276..57bae3ebf 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -353,7 +353,7 @@ extern inline void sx_long_delay(unsigned long delay)
{
unsigned long i;
- for (i = jiffies + delay; i > jiffies; ) ;
+ for (i = jiffies + delay; time_after(i, jiffies); ) ;
}
@@ -1073,7 +1073,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p
/* Set baud rate for port */
tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] +
CD186x_TPC/2) / CD186x_TPC);
- if ((tmp < 0x10) && (again < jiffies)) {
+ if ((tmp < 0x10) && time_before(again, jiffies)) {
again = jiffies + HZ * 60;
/* Page 48 of version 2.0 of the CL-CD1865 databook */
if (tmp >= 12) {
@@ -1551,8 +1551,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
timeout = jiffies+HZ;
while(port->IER & IER_TXEMPTY) {
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(port->timeout);
- if (jiffies > timeout) {
+ schedule_timeout(port->timeout);
+ if (time_after(jiffies, timeout)) {
printk (KERN_INFO "Timeout waiting for close\n");
break;
}
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 0b2f495b1..dd27a4e26 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -1697,7 +1697,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
if (signal_pending(current))
break;
stl_delay(2);
- if (jiffies >= tend)
+ if (time_after_eq(jiffies, tend))
break;
}
}
diff --git a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
index 4878d877e..30e0260b7 100644
--- a/drivers/char/tpqic02.c
+++ b/drivers/char/tpqic02.c
@@ -571,7 +571,7 @@ static int wait_for_ready(time_t timeout)
timeout -= spin_t;
spin_t += jiffies;
- while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (jiffies<spin_t))
+ while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t))
schedule(); /* don't waste all the CPU time */
if ((stat & QIC02_STAT_READY) == 0)
return TE_OK;
@@ -586,7 +586,7 @@ static int wait_for_ready(time_t timeout)
TPQDEB({printk("wait_for_ready: additional timeout: %d\n", spin_t);})
/* not ready and no exception && timeout not expired yet */
- while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (jiffies<spin_t)) {
+ while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t)) {
/* be `nice` to other processes on long operations... */
current->state = TASK_INTERRUPTIBLE;
/* nap 0.30 sec between checks, */
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 192e5350c..05a4f246e 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -77,9 +77,7 @@
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/poll.h>
-#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
-#endif
#include <linux/init.h>
#include <linux/smp_lock.h>
@@ -91,9 +89,7 @@
#include <linux/vt_kern.h>
#include <linux/selection.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
#define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
@@ -221,7 +217,6 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
return -EINVAL;
-#ifdef CONFIG_KMOD
/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
/* Cyrus Durgin <cider@speakeasy.org> */
if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
@@ -229,7 +224,6 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
sprintf(modname, "tty-ldisc-%d", ldisc);
request_module (modname);
}
-#endif
if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
return -EINVAL;
@@ -868,12 +862,7 @@ static int init_dev(kdev_t device, struct tty_struct **ret_tty)
* Failures after this point use release_mem to clean up, so
* there's no need to null out the local pointers.
*/
- driver->table[idx] = tty; /* FIXME: this is broken and
- probably causes ^D bug. tty->private_date does not (yet) point
- to a console, if keypress comes now, await armagedon.
-
- also, driver->table is accessed from interrupt for vt case,
- and this does not look like atomic access at all. */
+ driver->table[idx] = tty;
if (!*tp_loc)
*tp_loc = tp;
@@ -1848,6 +1837,10 @@ static void flush_to_ldisc(void *private_)
int count;
unsigned long flags;
+ if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ return;
+ }
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
@@ -1874,14 +1867,22 @@ static void flush_to_ldisc(void *private_)
/*
* Routine which returns the baud rate of the tty
- */
-
-/*
- * This is used to figure out the divisor speeds and the timeouts
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
*/
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 };
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+ 76800, 153600, 307200, 614400, 921600
+#else
+ 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+ 2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+static int n_baud_table = sizeof(baud_table)/sizeof(int);
int tty_get_baud_rate(struct tty_struct *tty)
{
@@ -1892,7 +1893,7 @@ int tty_get_baud_rate(struct tty_struct *tty)
i = cflag & CBAUD;
if (i & CBAUDEX) {
i &= ~CBAUDEX;
- if (i < 1 || i > 4)
+ if (i < 1 || i+15 >= n_baud_table)
tty->termios->c_cflag &= ~CBAUDEX;
else
i += 15;
@@ -1932,6 +1933,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
tty->flip.pty_sem = MUTEX;
tty->tq_hangup.routine = do_tty_hangup;
tty->tq_hangup.data = tty;
+ sema_init(&tty->atomic_read, 1);
}
/*
@@ -1966,9 +1968,7 @@ int tty_register_driver(struct tty_driver *driver)
if (tty_drivers) tty_drivers->prev = driver;
tty_drivers = driver;
-#ifdef CONFIG_PROC_FS
proc_tty_register_driver(driver);
-#endif
return error;
}
@@ -2010,9 +2010,7 @@ int tty_unregister_driver(struct tty_driver *driver)
if (driver->next)
driver->next->prev = driver->prev;
-#ifdef CONFIG_PROC_FS
proc_tty_unregister_driver(driver);
-#endif
return 0;
}
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 6a1d1c649..2cad9dba6 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -52,7 +52,6 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout)
if (!tty->driver.chars_in_buffer)
return;
add_wait_queue(&tty->write_wait, &wait);
- current->counter = 0; /* make us low-priority */
if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
do {
@@ -210,11 +209,12 @@ static int get_sgflags(struct tty_struct * tty)
{
int flags = 0;
- if (!(tty->termios->c_lflag & ICANON))
+ if (!(tty->termios->c_lflag & ICANON)) {
if (tty->termios->c_lflag & ISIG)
flags |= 0x02; /* cbreak */
else
flags |= 0x20; /* raw */
+ }
if (tty->termios->c_lflag & ECHO)
flags |= 0x08; /* echo */
if (tty->termios->c_oflag & OPOST)
diff --git a/drivers/char/tuner.c b/drivers/char/tuner.c
index 7f7471e19..1a96bec11 100644
--- a/drivers/char/tuner.c
+++ b/drivers/char/tuner.c
@@ -6,19 +6,31 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/malloc.h>
+#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/videodev.h>
#include "tuner.h"
-static int debug = 0; /* insmod parameter */
-static int type = 0; /* tuner type */
+static int debug = 0; /* insmod parameter */
+static int type = -1; /* tuner type */
#define dprintk if (debug) printk
+#if LINUX_VERSION_CODE > 0x020100
MODULE_PARM(debug,"i");
MODULE_PARM(type,"i");
+#endif
+
+#if LINUX_VERSION_CODE < 0x02017f
+void schedule_timeout(int j)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + j;
+ schedule();
+}
+#endif
struct tuner
{
@@ -69,9 +81,10 @@ static struct tunertype tuners[] = {
{"Temic NTSC", TEMIC, NTSC,
16*157.25,16*463.25,0x02,0x04,0x01,0x8e,0xc2,732},
{"TEMIC PAL_I", TEMIC, PAL_I,
- 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
+ // 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,0xc2,623},
+ 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,0xc2,623},
{"Temic 4036 FY5 NTSC", TEMIC, NTSC,
- 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
+ 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,0xc2,732},
};
/* ---------------------------------------------------------------------- */
@@ -98,11 +111,17 @@ static int tuner_afcstatus (struct tuner *t)
static void set_tv_freq(struct tuner *t, int freq)
{
- unsigned long flags;
u8 config;
u16 div;
- struct tunertype *tun=&tuners[t->type];
+ struct tunertype *tun;
+ LOCK_FLAGS;
+ if (t->type == -1) {
+ printk("tuner: tuner type not set\n");
+ return;
+ }
+
+ tun=&tuners[t->type];
if (freq < tun->thresh1)
config = tun->VHF_L;
else if (freq < tun->thresh2)
@@ -125,11 +144,17 @@ static void set_tv_freq(struct tuner *t, int freq)
static void set_radio_freq(struct tuner *t, int freq)
{
- unsigned long flags;
u8 config;
u16 div;
- struct tunertype *tun=&tuners[type];
+ struct tunertype *tun;
+ LOCK_FLAGS;
+
+ if (t->type == -1) {
+ printk("tuner: tuner type not set\n");
+ return;
+ }
+ tun=&tuners[t->type];
config = 0xa5;
div=freq + (int)(16*10.7);
div&=0x7fff;
@@ -143,7 +168,7 @@ static void set_radio_freq(struct tuner *t, int freq)
}
if (debug) {
UNLOCK_I2C_BUS(t->bus);
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ/10);
LOCK_I2C_BUS(t->bus);
@@ -181,7 +206,8 @@ static int tuner_attach(struct i2c_device *device)
t->bus = device->bus;
t->addr = device->addr;
t->type = type;
- dprintk("tuner: type is %d (%s)\n",t->type,tuners[t->type].name);
+ dprintk("tuner: type is %d (%s)\n",t->type,
+ (t->type == -1 ) ? "autodetect" : tuners[t->type].name);
MOD_INC_USE_COUNT;
return 0;
@@ -204,6 +230,8 @@ static int tuner_command(struct i2c_device *device,
switch (cmd)
{
case TUNER_SET_TYPE:
+ if (t->type != -1)
+ return 0;
t->type = *iarg;
dprintk("tuner: type set to %d (%s)\n",
t->type,tuners[t->type].name);
diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c
index def6e7039..dd9364ecf 100644
--- a/drivers/char/videodev.c
+++ b/drivers/char/videodev.c
@@ -15,6 +15,7 @@
*/
#include <linux/config.h>
+#include <linux/version.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -24,12 +25,12 @@
#include <linux/errno.h>
#include <linux/videodev.h>
+#if LINUX_VERSION_CODE >= 0x020100
#include <asm/uaccess.h>
+#endif
#include <asm/system.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#define VIDEO_NUM_DEVICES 256
@@ -68,6 +69,9 @@ extern int fmi_init(struct video_init *);
#ifdef CONFIG_RADIO_MIROPCM20
extern int pcm20_init(struct video_init *);
#endif
+#ifdef CONFIG_RADIO_GEMTEK
+extern int gemtek_init(struct video_init *);
+#endif
#ifdef CONFIG_VIDEO_PMS
extern int init_pms_cards(struct video_init *);
#endif
@@ -100,14 +104,17 @@ static struct video_init video_init_list[]={
#endif
#ifdef CONFIG_RADIO_SF16FMI
{"SF16FMI", fmi_init},
-#endif
+#endif
#ifdef CONFIG_RADIO_MIROPCM20
{"PCM20", pcm20_init},
-#endif
+#endif
+#ifdef CONFIG_RADIO_GEMTEK
+ {"GemTek", gemtek_init},
+#endif
{"end", NULL}
};
-
+#if LINUX_VERSION_CODE >= 0x020100
/*
* Read will do some smarts later on. Buffer pin etc.
*/
@@ -123,6 +130,7 @@ static ssize_t video_read(struct file *file,
}
+
/*
* Write for now does nothing. No reason it shouldnt do overlay setting
* for some boards I guess..
@@ -138,7 +146,6 @@ static ssize_t video_write(struct file *file, const char *buf,
return 0;
}
-
/*
* Poll to see if we're readable, can probably be used for timing on incoming
* frames, etc..
@@ -153,6 +160,32 @@ static unsigned int video_poll(struct file *file, poll_table * wait)
return 0;
}
+
+#else
+static int video_read(struct inode *ino,struct file *file,
+ char *buf, int count)
+{
+ int err;
+ struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
+ if (vfl->read)
+ return vfl->read(vfl, buf, count, file->f_flags&O_NONBLOCK);
+ else
+ return -EINVAL;
+}
+
+static int video_write(struct inode *ino,struct file *file, const char *buf,
+ int count)
+{
+ int err;
+ struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
+ if (vfl->write)
+ return vfl->write(vfl, buf, count, file->f_flags&O_NONBLOCK);
+ else
+ return 0;
+}
+
+#endif
+
/*
* Open a video device.
*/
@@ -168,14 +201,12 @@ static int video_open(struct inode *inode, struct file *file)
vfl=video_device[minor];
if(vfl==NULL) {
-#ifdef CONFIG_KMOD
char modname[20];
sprintf (modname, "char-major-%d-%d", VIDEO_MAJOR, minor);
request_module(modname);
vfl=video_device[minor];
if (vfl==NULL)
-#endif
return -ENODEV;
}
if(vfl->busy)
@@ -212,11 +243,19 @@ static int video_release(struct inode *inode, struct file *file)
* image ?
*/
+#if LINUX_VERSION_CODE >= 0x020100
static long long video_lseek(struct file * file,
long long offset, int origin)
{
return -ESPIPE;
}
+#else
+static long long video_lseek(struct inode *inode, struct file * file,
+ long long offset, int origin)
+{
+ return -ESPIPE;
+}
+#endif
static int video_ioctl(struct inode *inode, struct file *file,
@@ -240,9 +279,16 @@ static int video_ioctl(struct inode *inode, struct file *file,
*/
+#if LINUX_VERSION_CODE >= 0x020100
int video_mmap(struct file *file, struct vm_area_struct *vma)
{
struct video_device *vfl=video_device[MINOR(file->f_dentry->d_inode->i_rdev)];
+#else
+static int video_mmap(struct inode * ino, struct file * file,
+ struct vm_area_struct * vma)
+{
+ struct video_device *vfl=video_device[MINOR(ino->i_rdev)];
+#endif
if(vfl->mmap)
return vfl->mmap(vfl, (char *)vma->vm_start,
(unsigned long)(vma->vm_end-vma->vm_start));
@@ -326,11 +372,17 @@ static struct file_operations video_fops=
video_read,
video_write,
NULL, /* readdir */
+#if LINUX_VERSION_CODE >= 0x020100
video_poll, /* poll */
+#else
+ NULL,
+#endif
video_ioctl,
video_mmap,
video_open,
+#if LINUX_VERSION_CODE >= 0x020100
NULL, /* flush */
+#endif
video_release
};
@@ -374,5 +426,7 @@ void cleanup_module(void)
#endif
+#if LINUX_VERSION_CODE >= 0x020100
EXPORT_SYMBOL(video_register_device);
EXPORT_SYMBOL(video_unregister_device);
+#endif
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index d365e30a2..d227ba9e0 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -22,7 +22,6 @@
#include <linux/malloc.h>
#include <linux/major.h>
#include <linux/fs.h>
-#include <linux/config.h>
#include <asm/io.h>
#include <asm/uaccess.h>
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 720453a87..8984a0fad 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -1,7 +1,7 @@
/* fc.c: Generic Fibre Channel and FC4 SCSI driver.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997,1998 Jiri Hanika (geo@ff.cuni.cz)
+ * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
*
* Sources:
* Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
diff --git a/drivers/fc4/fcp_scsi.h b/drivers/fc4/fcp_scsi.h
index 3717740c7..1e194cdf6 100644
--- a/drivers/fc4/fcp_scsi.h
+++ b/drivers/fc4/fcp_scsi.h
@@ -1,7 +1,7 @@
/* fcp_scsi.h: Generic SCSI on top of FC4 - interface defines.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1998 Jiri Hanika (geo@ff.cuni.cz)
+ * Copyright (C) 1998 Jirka Hanika (geo@ff.cuni.cz)
*/
#ifndef _FCP_SCSI_H
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
index 3d23f6b19..2f9bfbc89 100644
--- a/drivers/fc4/soc.c
+++ b/drivers/fc4/soc.c
@@ -1,7 +1,7 @@
/* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support.
*
* Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997,1998 Jiri Hanika (geo@ff.cuni.cz)
+ * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
*
* Sources:
* Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
@@ -20,7 +20,7 @@
*/
static char *version =
- "soc.c:v1.2 27/Feb/98 Jakub Jelinek (jj@sunsite.mff.cuni.cz), Jiri Hanika (geo@ff.cuni.cz)\n";
+ "soc.c:v1.2 27/Feb/98 Jakub Jelinek (jj@sunsite.mff.cuni.cz), Jirka Hanika (geo@ff.cuni.cz)\n";
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in
index 3787c735f..08e3b78b8 100644
--- a/drivers/isdn/Config.in
+++ b/drivers/isdn/Config.in
@@ -38,7 +38,9 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+ fi
fi
fi
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
diff --git a/drivers/isdn/avmb1/b1lli.c b/drivers/isdn/avmb1/b1lli.c
index 1c4c0b806..db6fe1453 100644
--- a/drivers/isdn/avmb1/b1lli.c
+++ b/drivers/isdn/avmb1/b1lli.c
@@ -173,7 +173,7 @@ static inline int B1_rx_full(unsigned short base)
static inline unsigned char B1_get_byte(unsigned short base)
{
unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */
- while (!B1_rx_full(base) && i > jiffies);
+ while (!B1_rx_full(base) && time_before(jiffies, i));
if (B1_rx_full(base))
return inb(base + B1_READ);
printk(KERN_CRIT "b1lli: rx not full after 5 second\n");
@@ -477,7 +477,7 @@ int B1_loaded(unsigned short base)
if (loaddebug)
printk(KERN_DEBUG "b1capi: loaded: wait 1 ..\n");
- for (i = jiffies + 10 * HZ; i > jiffies;) {
+ for (i = jiffies + 10 * HZ; time_before(jiffies, i);) {
if (B1_tx_empty(base))
break;
}
@@ -487,7 +487,7 @@ int B1_loaded(unsigned short base)
}
B1_put_byte(base, SEND_POLL);
printk(KERN_DEBUG "b1capi: loaded: wait 2 ..\n");
- for (i = jiffies + 10 * HZ; i > jiffies;) {
+ for (i = jiffies + 10 * HZ; time_before(jiffies, i);) {
if (B1_rx_full(base)) {
if ((ans = B1_get_byte(base)) == RECEIVE_POLL) {
if (loaddebug)
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 6924e3f9e..bcd305058 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -62,7 +62,7 @@
#include "hisax.h"
#ifdef MODULE
-#define MOD_USE_COUNT ((&__this_module)->usecount)
+#define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
#endif /* MODULE */
const char *lli_revision = "$Revision: 2.13 $";
@@ -2055,7 +2055,7 @@ HiSax_command(isdn_ctrl * ic)
if (csta->channel[0].debug & 0x400) {
jiftime(tmp, jiffies);
i = strlen(tmp);
- sprintf(tmp + i, " LOCK modcnt %lx\n", MOD_USE_COUNT);
+ sprintf(tmp + i, " LOCK modcnt %d\n", MOD_USE_COUNT);
HiSax_putstatus(csta, tmp);
}
#endif /* MODULE */
@@ -2066,7 +2066,7 @@ HiSax_command(isdn_ctrl * ic)
if (csta->channel[0].debug & 0x400) {
jiftime(tmp, jiffies);
i = strlen(tmp);
- sprintf(tmp + i, " UNLOCK modcnt %lx\n", MOD_USE_COUNT);
+ sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT);
HiSax_putstatus(csta, tmp);
}
#endif /* MODULE */
@@ -2128,7 +2128,8 @@ HiSax_command(isdn_ctrl * ic)
break;
#ifdef MODULE
case (55):
- MOD_USE_COUNT = 0;
+ while ( MOD_USE_COUNT > 0)
+ MOD_DEC_USE_COUNT;
HiSax_mod_inc_use_count();
break;
#endif /* MODULE */
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 67e308e43..e6b3a9a52 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -97,9 +97,11 @@
#ifdef CONFIG_HISAX_ELSA
#define DEFAULT_CARD ISDN_CTYPE_ELSA
#define DEFAULT_CFG {0,0,0,0}
+#ifdef MODULE
int elsa_init_pcmcia(void*, int, int*, int);
EXPORT_SYMBOL(elsa_init_pcmcia);
#endif
+#endif
#ifdef CONFIG_HISAX_AVM_A1
#undef DEFAULT_CARD
#undef DEFAULT_CFG
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index 3bd2819ce..4aba68b38 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -318,9 +318,9 @@ static char *icn_id2 = "\0";
#ifdef MODULE
MODULE_AUTHOR("Fritz Elfert");
MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port adress of first card");
+MODULE_PARM_DESC(portbase, "Port address of first card");
MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
+MODULE_PARM_DESC(membase, "Shared memory address of all cards");
MODULE_PARM(icn_id, "s");
MODULE_PARM_DESC(icn_id, "ID-String of first card");
MODULE_PARM(icn_id2, "s");
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index 331842fab..92e2ee544 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -20,6 +20,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_common.c,v $
* Revision 1.55 1998/02/23 23:35:32 fritz
* Eliminated some compiler warnings.
@@ -770,9 +774,18 @@ isdn_getnum(char **p)
/*
* isdn_readbchan() tries to get data from the read-queue.
* It MUST be called with interrupts off.
+ *
+ * Be aware that this is not an atomic operation when sleep != 0, even though
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he
*/
int
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
{
int left;
int count;
@@ -785,8 +798,8 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user
if (!dev->drv[di])
return 0;
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
- if (user)
- interruptible_sleep_on(&dev->drv[di]->rcv_waitq[channel]);
+ if (sleep)
+ interruptible_sleep_on(sleep);
else
return 0;
}
@@ -808,16 +821,10 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user
count_pull = count_put = 0;
while ((count_pull < skb->len) && (left-- > 0)) {
if (dev->drv[di]->DLEflag & DLEmask) {
- if (user)
- put_user(DLE, cp++);
- else
- *cp++ = DLE;
+ *cp++ = DLE;
dev->drv[di]->DLEflag &= ~DLEmask;
} else {
- if (user)
- put_user(*p, cp++);
- else
- *cp++ = *p;
+ *cp++ = *p;
if (*p == DLE) {
dev->drv[di]->DLEflag |= DLEmask;
(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
@@ -838,10 +845,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user
dflag = 0;
}
count_put = count_pull;
- if (user)
- copy_to_user(cp, skb->data, count_put);
- else
- memcpy(cp, skb->data, count_put);
+ memcpy(cp, skb->data, count_put);
cp += count_put;
left -= count_put;
#ifdef CONFIG_ISDN_AUDIO
@@ -966,12 +970,12 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
ulong flags;
int drvidx;
int chidx;
+ char *p;
if (off != &file->f_pos)
return -ESPIPE;
if (minor == ISDN_MINOR_STATUS) {
- char *p;
if (!file->private_data) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -996,11 +1000,15 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
if (!dev->drv[drvidx]->running)
return -ENODEV;
chidx = isdn_minor2chan(minor);
+ if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM;
save_flags(flags);
cli();
- len = isdn_readbchan(drvidx, chidx, buf, 0, count, 1);
+ len = isdn_readbchan(drvidx, chidx, p, 0, count,
+ &dev->drv[drvidx]->rcv_waitq[chidx]);
*off += len;
restore_flags(flags);
+ if( copy_to_user(buf,p,len) ) len = -EFAULT;
+ kfree(p);
return len;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
@@ -1124,6 +1132,11 @@ isdn_poll(struct file *file, poll_table * wait)
return POLLERR;
}
+/*
+ * This accesses user space with interrupts off, but is not needed by
+ * any of the isdn4k-util programs anyway. Thus, in contrast to your
+ * first impression after looking at the code, fixing is trival!*/
+#if 0
static int
isdn_set_allcfg(char *src)
{
@@ -1135,8 +1148,7 @@ isdn_set_allcfg(char *src)
if ((ret = isdn_net_rmall()))
return ret;
- if ((ret = copy_from_user((char *) &i, src, sizeof(int))))
- return ret;
+ if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT;
save_flags(flags);
cli();
src += sizeof(int);
@@ -1144,9 +1156,9 @@ isdn_set_allcfg(char *src)
int phone_len;
int out_flag;
- if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) {
+ if (copy_from_user((char *) &cfg, src, sizeof(cfg))) {
restore_flags(flags);
- return ret;
+ return -EFAULT;
}
src += sizeof(cfg);
if (!isdn_net_new(cfg.name, NULL)) {
@@ -1256,6 +1268,7 @@ isdn_get_allcfg(char *dest)
restore_flags(flags);
return 0;
}
+#endif
static int
isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1319,59 +1332,83 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return 0;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
+/*
+ * isdn net devices manage lots of configuration variables as linked lists.
+ * Those lists must only be manipulated from user space. Some of the ioctl's
+ * service routines access user space and are not atomic. Therefor, ioctl's
+ * manipulating the lists and ioctl's sleeping while accessing the lists
+ * are serialized by means of a semaphore.
+ */
switch (cmd) {
#ifdef CONFIG_NETDEVICES
case IIOCNETAIF:
/* Add a network-interface */
if (arg) {
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
s = name;
- } else
+ } else {
s = NULL;
+ }
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
if ((s = isdn_net_new(s, NULL))) {
- if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
+ if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+ ret = -EFAULT;
+ } else {
+ ret = 0;
+ }
} else
- return -ENODEV;
+ ret = -ENODEV;
+ up(&dev->sem);
+ return ret;
case IIOCNETASL:
/* Add a slave to a network-interface */
if (arg) {
- if ((ret = copy_from_user(bname, (char *) arg, sizeof(bname) - 1)))
- return ret;
+ if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
+ return -EFAULT;
} else
return -EINVAL;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
if ((s = isdn_net_newslave(bname))) {
- if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
+ if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+ ret = -EFAULT;
+ } else {
+ ret = 0;
+ }
} else
- return -ENODEV;
+ ret = -ENODEV;
+ up(&dev->sem);
+ return ret;
case IIOCNETDIF:
/* Delete a network-interface */
if (arg) {
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_net_rm(name);
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_rm(name);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETSCF:
/* Set configurable parameters of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
- return ret;
+ if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
return isdn_net_setcfg(&cfg);
} else
return -EINVAL;
case IIOCNETGCF:
/* Get configurable parameters of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
- return ret;
+ if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
if (!(ret = isdn_net_getcfg(&cfg))) {
- if ((ret = copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))))
- return ret;
+ if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+ return -EFAULT;
}
return ret;
} else
@@ -1379,32 +1416,44 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
case IIOCNETANM:
/* Add a phone-number to a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_addphone(&phone);
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_addphone(&phone);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETGNM:
/* Get list of phone-numbers of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_getphones(&phone, (char *) arg);
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_getphones(&phone, (char *) arg);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETDNM:
/* Delete a phone-number of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_delphone(&phone);
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_delphone(&phone);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETDIL:
/* Force dialing of a network-interface */
if (arg) {
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_net_force_dial(name);
} else
return -EINVAL;
@@ -1412,22 +1461,22 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
case IIOCNETALN:
if (!arg)
return -EINVAL;
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_ppp_dial_slave(name);
case IIOCNETDLN:
if (!arg)
return -EINVAL;
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_ppp_hangup_slave(name);
#endif
case IIOCNETHUP:
/* Force hangup of a network-interface */
if (!arg)
return -EINVAL;
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_net_force_hangup(name);
break;
#endif /* CONFIG_NETDEVICES */
@@ -1448,9 +1497,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
int i;
char *p;
- if ((ret = copy_from_user((char *) &iocts, (char *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
+ if (copy_from_user((char *) &iocts, (char *) arg,
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1466,6 +1515,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return -ENODEV;
dev->drv[drvidx]->reject_bus = iocts.arg;
return 0;
+#if 0
case IIOCGETSET:
/* Get complete setup (all network-interfaces and profile-
settings of all tty-devices */
@@ -1482,6 +1532,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
else
return -EINVAL;
break;
+#endif
case IIOCSIGPRF:
dev->profd = current;
return 0;
@@ -1522,12 +1573,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return ret;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if ((ret = copy_from_user(dev->mdm.info[i].emu.profile, p,
- ISDN_MODEM_ANZREG)))
- return ret;
+ if (copy_from_user(dev->mdm.info[i].emu.profile, p,
+ ISDN_MODEM_ANZREG))
+ return -EFAULT;
p += ISDN_MODEM_ANZREG;
- if ((ret = copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)))
- return ret;
+ if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+ return -EFAULT;
p += ISDN_MSNLEN;
}
return 0;
@@ -1539,10 +1590,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
/* Set/Get MSN->EAZ-Mapping for a driver */
if (arg) {
- if ((ret = copy_from_user((char *) &iocts,
+ if (copy_from_user((char *) &iocts,
(char *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
if (strlen(iocts.drvid)) {
drvidx = -1;
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1591,8 +1642,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
strlen(dev->drv[drvidx]->msn2eaz[i]) ?
dev->drv[drvidx]->msn2eaz[i] : "-",
(i < 9) ? "," : "\0");
- if ((ret = copy_to_user(p, bname, strlen(bname) + 1)))
- return ret;
+ if (copy_to_user(p, bname, strlen(bname) + 1))
+ return -EFAULT;
p += strlen(bname);
}
}
@@ -1601,8 +1652,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return -EINVAL;
case IIOCDBGVAR:
if (arg) {
- if ((ret = copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))))
- return ret;
+ if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
+ return -EFAULT;
return 0;
} else
return -EINVAL;
@@ -1615,8 +1666,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
int i;
char *p;
- if ((ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))))
- return ret;
+ if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1639,7 +1690,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
ret = isdn_command(&c);
memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
- if ((copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))))
+ if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
return -EFAULT;
return ret;
} else
@@ -2164,6 +2215,7 @@ isdn_init(void)
memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
+ dev->sem = MUTEX;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
dev->drvmap[i] = -1;
dev->chanmap[i] = -1;
diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h
index b9d5df715..6cb503b9f 100644
--- a/drivers/isdn/isdn_common.h
+++ b/drivers/isdn/isdn_common.h
@@ -20,6 +20,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_common.h,v $
* Revision 1.9 1998/02/20 17:19:01 fritz
* Added common stub for sending commands to lowlevel.
@@ -86,7 +90,7 @@ extern char *isdn_map_eaz2msn(char *msn, int di);
extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, int);
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
extern int isdn_get_free_channel(int, int, int, int, int);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index 33b122c96..daafceb1a 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -20,6 +20,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_net.c,v $
* Revision 1.55 1998/02/23 19:38:22 fritz
* Corrected check for modified feature-flags.
@@ -243,7 +247,7 @@
#include <linux/module.h>
#include <linux/isdn.h>
#include <net/arp.h>
-#include <net/icmp.h>
+#include <net/dst.h>
#ifndef DEV_NUMBUFFS
#include <net/pkt_sched.h>
#endif
@@ -277,9 +281,18 @@ char *isdn_net_revision = "$Revision: 1.55 $";
static void
isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
{
- printk(KERN_DEBUG "isdn_net: %s: %s, send ICMP\n",
- dev->name, reason);
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+
+ if(skb) {
+
+ u_short proto = ntohs(skb->protocol);
+
+ printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
+ dev->name,
+ (reason != NULL) ? reason : "unknown",
+ (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
+
+ dst_link_failure(skb);
+ }
}
static void
@@ -610,6 +623,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
lp->first_skb = NULL;
+ } else {
+ /*
+ * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
+ * With an empty lp->first_skb, we need to do this ourselves
+ */
+ lp->netdev->dev.tbusy = 0;
+ mark_bh(NET_BH);
}
return 1;
}
@@ -2696,7 +2716,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
}
/*
- * Return a string of all phone-numbers of an interface.
+ * Copy a string of all phone-numbers of an interface to user space.
+ * This might sleep and must be called with the isdn semaphore down.
*/
int
isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
@@ -2706,22 +2727,17 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
int more = 0;
int count = 0;
isdn_net_phone *n;
- int flags;
- int ret;
if (!p)
return -ENODEV;
- save_flags(flags);
- cli();
inout &= 1;
for (n = p->local->phone[inout]; n; n = n->next) {
if (more) {
put_user(' ', phones++);
count++;
}
- if ((ret = copy_to_user(phones, n->num, strlen(n->num) + 1))) {
- restore_flags(flags);
- return ret;
+ if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
+ return -EFAULT;
}
phones += strlen(n->num);
count += strlen(n->num);
@@ -2729,7 +2745,6 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
}
put_user(0, phones);
count++;
- restore_flags(flags);
return count;
}
@@ -2760,6 +2775,7 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
else
p->local->phone[inout] = n->next;
kfree(n);
+ restore_flags(flags);
return 0;
}
m = n;
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index a4a45d9ea..5da3a49f0 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -18,6 +18,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_ppp.c,v $
* Revision 1.33 1998/02/20 17:11:54 fritz
* Changes for recent kernels.
@@ -500,11 +504,10 @@ isdn_ppp_release(int min, struct file *file)
static int
get_arg(void *b, void *val, int len)
{
- int r;
if (len <= 0)
len = sizeof(unsigned long);
- if ((r = copy_from_user((void *) val, b, len)))
- return r;
+ if (copy_from_user((void *) val, b, len))
+ return -EFAULT;
return 0;
}
@@ -514,13 +517,12 @@ get_arg(void *b, void *val, int len)
static int
set_arg(void *b, unsigned long val, void *str)
{
- int r;
if (!str) {
- if ((r = copy_to_user(b, (void *) &val, 4)))
- return r;
+ if (copy_to_user(b, (void *) &val, 4))
+ return -EFAULT;
} else {
- if ((r = copy_to_user(b, str, val)))
- return r;
+ if (copy_to_user(b, str, val))
+ return -EFAULT;
}
return 0;
}
@@ -1851,13 +1853,14 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct device *dev)
}
#endif
}
- return copy_to_user(res, &t, sizeof(struct ppp_stats));
+ if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT;
+ return 0;
}
int
isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
- int error;
+ int error=0;
char *r;
int len;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -1873,7 +1876,7 @@ isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
case SIOCGPPPVER:
r = (char *) ifr->ifr_ifru.ifru_data;
len = strlen(PPP_VERSION) + 1;
- error = copy_to_user(r, PPP_VERSION, len);
+ if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
break;
case SIOCGPPPSTATS:
error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
diff --git a/drivers/isdn/isdn_x25iface.c b/drivers/isdn/isdn_x25iface.c
index c7471d361..2ae21fcf3 100644
--- a/drivers/isdn/isdn_x25iface.c
+++ b/drivers/isdn/isdn_x25iface.c
@@ -65,7 +65,7 @@ static struct concap_proto_ops ix25_pops = {
&isdn_x25iface_disconn_ind
};
-/* error message helper fuction */
+/* error message helper function */
static void illegal_state_warn( unsigned state, unsigned char firstbyte)
{
printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 5af8ad871..84f88cd75 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -1328,7 +1328,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
schedule_timeout(char_time);
if (signal_pending(current))
break;
- if (timeout && ((orig_jiffies + timeout) < jiffies))
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
current->state = TASK_RUNNING;
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 13ce064f4..30ecbd4e0 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -180,7 +180,7 @@ check_media_bay(struct device_node *which_bay, int what)
{
#ifdef CONFIG_BLK_DEV_IDE
int i;
-
+
for (i=0; i<media_bay_count; i++)
if (which_bay == media_bays[i].dev_node)
{
@@ -196,9 +196,9 @@ check_media_bay(struct device_node *which_bay, int what)
int
check_media_bay_by_base(unsigned long base, int what)
{
+#ifdef CONFIG_BLK_DEV_IDE
int i;
-#ifdef CONFIG_BLK_DEV_IDE
for (i=0; i<media_bay_count; i++)
if (base == media_bays[i].cd_base)
{
@@ -216,9 +216,9 @@ int
media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
int irq, int index)
{
- int i;
-
#ifdef CONFIG_BLK_DEV_IDE
+ int i;
+
for (i=0; i<media_bay_count; i++)
if (which_bay == media_bays[i].dev_node)
{
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 4dd82fef9..3b027da3f 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -523,7 +523,7 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
int intr;
int nloop = 0;
- while ((intr = (in_8(&via[IFR]) & (SR_INT | CB1_INT))) != 0) {
+ while ((intr = in_8(&via[IFR])) != 0) {
if (++nloop > 1000) {
printk(KERN_DEBUG "PMU: stuck in intr loop, "
"intr=%x pmu_state=%d\n", intr, pmu_state);
@@ -534,6 +534,12 @@ via_pmu_interrupt(int irq, void *arg, struct pt_regs *regs)
else if (intr & CB1_INT) {
adb_int_pending = 1;
out_8(&via[IFR], CB1_INT);
+ } else
+ {
+ /* -- Disabled printk, will happen _really_ often on
+ PowerBooks ((CB2 interrupts) --
+ printk(KERN_DEBUG "PMU: spurrious interrupt intr=%x\n", intr); */
+ out_8(&via[IFR], intr);
}
}
if (pmu_state == idle) {
@@ -750,7 +756,8 @@ pmu_restart(void)
_disable_interrupts();
- pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT);
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+ PMU_INT_TICK );
while(!req.complete)
pmu_poll();
@@ -768,7 +775,8 @@ pmu_shutdown(void)
_disable_interrupts();
- pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT);
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+ PMU_INT_TICK );
while(!req.complete)
pmu_poll();
@@ -886,7 +894,7 @@ int powerbook_sleep(void)
pmu_enable_backlight(0);
/* Give the disks a little time to actually finish writing */
- for (wait = jiffies + (HZ/4); jiffies < wait; )
+ for (wait = jiffies + (HZ/4); time_before(jiffies, wait); )
mb();
/* Disable all interrupts except pmu */
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 9b4aab919..174c8d413 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -19,10 +19,7 @@ MI_OBJS :=
MIX_OBJS :=
ifeq ($(CONFIG_PARPORT),y)
- L_OBJS += parport_share.o parport_ieee1284.o
- ifeq ($(CONFIG_PROC_FS),y)
- L_OBJS += parport_procfs.o
- endif
+ L_OBJS += parport_share.o parport_ieee1284.o parport_procfs.o
ifeq ($(CONFIG_PARPORT_PC),y)
LX_OBJS += parport_pc.o
else
diff --git a/drivers/misc/parport_arc.c b/drivers/misc/parport_arc.c
index 134bec7d7..37c1e4e9a 100644
--- a/drivers/misc/parport_arc.c
+++ b/drivers/misc/parport_arc.c
@@ -14,7 +14,6 @@
* a subset of the standard printer control lines connected.
*/
-#include <linux/config.h>
#include <linux/tasks.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -142,9 +141,7 @@ int parport_arc_init(void)
printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
p->irq);
-#ifdef CONFIG_PROC_FS
parport_proc_register(p);
-#endif
p->flags |= PARPORT_FLAG_COMA;
if (parport_probe_hook)
diff --git a/drivers/misc/parport_ax.c b/drivers/misc/parport_ax.c
index 463884533..77738b0e1 100644
--- a/drivers/misc/parport_ax.c
+++ b/drivers/misc/parport_ax.c
@@ -11,7 +11,6 @@
* Grant Guenther <grant@torque.net>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -586,9 +585,7 @@ init_one_port(struct linux_ebus_device *dev)
printmode(ECPPS2);
}
printk("]\n");
-#ifdef CONFIG_PROC_FS
parport_proc_register(p);
-#endif
p->flags |= PARPORT_FLAG_COMA;
p->ops->write_control(p, 0x0c);
@@ -631,9 +628,7 @@ cleanup_module(void)
if (p->modes & PARPORT_MODE_PCSPP) {
if (!(p->flags & PARPORT_FLAG_COMA))
parport_quiesce(p);
-#ifdef CONFIG_PROC_FS
parport_proc_unregister(p);
-#endif
parport_unregister_port(p);
}
p = tmp;
diff --git a/drivers/misc/parport_ieee1284.c b/drivers/misc/parport_ieee1284.c
index 3fa369ea7..668cf67a2 100644
--- a/drivers/misc/parport_ieee1284.c
+++ b/drivers/misc/parport_ieee1284.c
@@ -1,4 +1,4 @@
-/* $Id: parport_ieee1284.c,v 1.4 1998/08/25 09:17:18 ralf Exp $
+/* $Id: parport_ieee1284.c,v 1.5 1999/01/04 16:06:00 ralf Exp $
* IEEE-1284 implementation for parport.
*
* Authors: Phil Blundell <Philip.Blundell@pobox.com>
@@ -47,8 +47,12 @@ int parport_wait_peripheral(struct parport *port, unsigned char mask,
*/
int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode)
{
+ /* make sure it's a valid state, set nStrobe & nAutoFeed high */
+ parport_write_control(port, (parport_read_control(port) \
+ & ~1 ) & ~2);
+ udelay(1);
parport_write_data(port, mode);
- udelay(500);
+ udelay(1);
/* nSelectIn high, nAutoFd low */
parport_write_control(port, (parport_read_control(port) & ~8) | 2);
if (parport_wait_peripheral(port, 0x78, 0x38)) {
@@ -58,11 +62,12 @@ int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode)
}
/* nStrobe low */
parport_write_control(port, parport_read_control(port) | 1);
- udelay(5); /* Strobe wait */
- /* nStrobe high */
- parport_write_control(port, parport_read_control(port) & ~1);
- udelay(5);
- /* nAutoFd low */
- parport_write_control(port, parport_read_control(port) & ~2);
- return (parport_wait_peripheral(port, 0x20, 0))?2:1;
+ udelay(1); /* Strobe wait */
+ /* nStrobe high, nAutoFeed low, last step before transferring
+ * reverse data */
+ parport_write_control(port, (parport_read_control(port) \
+ & ~1) & ~2);
+ udelay(1);
+ /* Data available? */
+ return (parport_wait_peripheral(port, 0x20, 0))?1:2;
}
diff --git a/drivers/misc/parport_init.c b/drivers/misc/parport_init.c
index 7fcefe436..473c1b224 100644
--- a/drivers/misc/parport_init.c
+++ b/drivers/misc/parport_init.c
@@ -98,19 +98,17 @@ __initfunc(void parport_setup(char *str, int *ints))
#ifdef MODULE
int init_module(void)
{
-#ifdef CONFIG_PROC_FS
(void)parport_proc_init(); /* We can go on without it. */
-#endif
return 0;
}
void cleanup_module(void)
{
-#ifdef CONFIG_PROC_FS
parport_proc_cleanup();
-#endif
}
+
#else
+
__initfunc(int parport_init(void))
{
if (io[0] == PARPORT_DISABLE)
@@ -145,10 +143,8 @@ EXPORT_SYMBOL(parport_unregister_device);
EXPORT_SYMBOL(parport_enumerate);
EXPORT_SYMBOL(parport_ieee1284_nibble_mode_ok);
EXPORT_SYMBOL(parport_wait_peripheral);
-#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(parport_proc_register);
EXPORT_SYMBOL(parport_proc_unregister);
-#endif
EXPORT_SYMBOL(parport_probe_hook);
EXPORT_SYMBOL(parport_parse_irqs);
diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c
index cddb1dffe..b51dbe1bd 100644
--- a/drivers/misc/parport_pc.c
+++ b/drivers/misc/parport_pc.c
@@ -759,8 +759,8 @@ static int probe_one_port(unsigned long int base, int irq, int dma)
#ifdef CONFIG_PROC_FS
if (probedirq != PARPORT_IRQ_NONE)
printk("%s: detected irq %d; use procfs to enable interrupt-driven operation.\n", p->name, probedirq);
- parport_proc_register(p);
#endif
+ parport_proc_register(p);
p->flags |= PARPORT_FLAG_COMA;
/* Done probing. Now put the port into a sensible start-up state. */
@@ -824,9 +824,7 @@ void cleanup_module(void)
if (p->modes & PARPORT_MODE_PCSPP) {
if (!(p->flags & PARPORT_FLAG_COMA))
parport_quiesce(p);
-#ifdef CONFIG_PROC_FS
parport_proc_unregister(p);
-#endif
parport_unregister_port(p);
}
p = tmp;
diff --git a/drivers/misc/parport_procfs.c b/drivers/misc/parport_procfs.c
index dd92e8957..2d276a573 100644
--- a/drivers/misc/parport_procfs.c
+++ b/drivers/misc/parport_procfs.c
@@ -12,6 +12,7 @@
* Cleaned up include files - Russell King <linux@arm.uk.linux.org>
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -27,6 +28,8 @@
#include <asm/dma.h>
#include <asm/irq.h>
+#ifdef CONFIG_PROC_FS
+
struct proc_dir_entry *base = NULL;
static int irq_write_proc(struct file *file, const char *buffer,
@@ -305,12 +308,11 @@ int parport_proc_init(void)
{
base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT,
NULL);
- base->fill_inode = &parport_modcount;
-
if (base == NULL) {
printk(KERN_ERR "Unable to initialise /proc/parport.\n");
return 0;
}
+ base->fill_inode = &parport_modcount;
return 1;
}
@@ -385,3 +387,26 @@ int parport_proc_unregister(struct parport *pp)
destroy_proc_tree(pp);
return 0;
}
+
+#else
+
+int parport_proc_register(struct parport *p)
+{
+ return 0;
+}
+
+int parport_proc_unregister(struct parport *p)
+{
+ return 0;
+}
+
+int parport_proc_init(void)
+{
+ return 0;
+}
+
+void parport_proc_cleanup(void)
+{
+}
+
+#endif
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 188de03d0..6c2a672ec 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -98,18 +98,18 @@ static const char *version =
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
-#define BLOCKOUT_2
-
/* A zero-terminated list of I/O addresses to be probed.
The 3c501 can be at many locations, but here are the popular ones. */
-static unsigned int netcard_portlist[] __initdata =
- { 0x280, 0x300, 0};
+static unsigned int netcard_portlist[] __initdata = {
+ 0x280, 0x300, 0
+};
/*
@@ -140,10 +140,11 @@ static int el_debug = EL_DEBUG;
struct net_local
{
- struct net_device_stats stats;
- int tx_pkt_start; /* The length of the current Tx packet. */
- int collisions; /* Tx collisions this packet */
- int loading; /* Spot buffer load collisions */
+ struct net_device_stats stats;
+ int tx_pkt_start; /* The length of the current Tx packet. */
+ int collisions; /* Tx collisions this packet */
+ int loading; /* Spot buffer load collisions */
+ spinlock_t lock; /* Serializing lock */
};
@@ -238,6 +239,7 @@ __initfunc(int el1_probe(struct device *dev))
__initfunc(static int el1_probe1(struct device *dev, int ioaddr))
{
+ struct net_local *lp;
const char *mname; /* Vendor name */
unsigned char station_addr[6];
int autoirq = 0;
@@ -327,6 +329,9 @@ __initfunc(static int el1_probe1(struct device *dev, int ioaddr))
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct net_local));
+ lp=dev->priv;
+ spin_lock_init(&lp->lock);
+
/*
* The EL1-specific entries in the device structure.
*/
@@ -398,24 +403,22 @@ static int el_start_xmit(struct sk_buff *skb, struct device *dev)
dev->trans_start = jiffies;
}
- save_flags(flags);
-
/*
* Avoid incoming interrupts between us flipping tbusy and flipping
* mode as the driver assumes tbusy is a faithful indicator of card
* state
*/
- cli();
-
+ spin_lock_irqsave(&lp->lock, flags);
+
/*
* Avoid timer-based retransmission conflicts.
*/
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
{
- restore_flags(flags);
- printk("%s: Transmitter access conflict.\n", dev->name);
+ spin_unlock_irqrestore(&lp->lock, flags);
+ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
}
else
{
@@ -433,9 +436,6 @@ load_it_again_sam:
* mean no more interrupts can be pending on the card.
*/
-#ifdef BLOCKOUT_1
- disable_irq(dev->irq);
-#endif
outb_p(AX_SYS, AX_CMD);
inb_p(RX_STATUS);
inb_p(TX_STATUS);
@@ -447,24 +447,22 @@ load_it_again_sam:
* loading bytes into the board
*/
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->lock, flags);
+
outw(0x00, RX_BUF_CLR); /* Set rx packet area to 0. */
outw(gp_start, GP_LOW); /* aim - packet will be loaded into buffer start */
outsb(DATAPORT,buf,skb->len); /* load buffer (usual thing each byte increments the pointer) */
outw(gp_start, GP_LOW); /* the board reuses the same register */
-#ifndef BLOCKOUT_1
+
if(lp->loading==2) /* A receive upset our load, despite our best efforts */
{
if(el_debug>2)
printk("%s: burped during tx load.\n", dev->name);
+ spin_lock_irqsave(&lp->lock, flags);
goto load_it_again_sam; /* Sigh... */
}
-#endif
outb(AX_XMIT, AX_CMD); /* fire ... Trigger xmit. */
lp->loading=0;
-#ifdef BLOCKOUT_1
- enable_irq(dev->irq);
-#endif
dev->trans_start = jiffies;
}
@@ -489,13 +487,15 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (dev == NULL || dev->irq != irq)
{
- printk ("3c501 driver: irq %d for unknown device.\n", irq);
+ printk (KERN_ERR "3c501 driver: irq %d for unknown device.\n", irq);
return;
}
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
+ spin_lock(&lp->lock);
+
/*
* What happened ?
*/
@@ -507,18 +507,13 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
if (el_debug > 3)
- printk("%s: el_interrupt() aux=%#02x", dev->name, axsr);
+ printk(KERN_DEBUG "%s: el_interrupt() aux=%#02x", dev->name, axsr);
if (dev->interrupt)
- printk("%s: Reentering the interrupt driver!\n", dev->name);
+ printk(KERN_WARNING "%s: Reentering the interrupt driver!\n", dev->name);
dev->interrupt = 1;
-#ifndef BLOCKOUT_1
if(lp->loading==1 && !dev->tbusy)
- printk("%s: Inconsistent state loading while not in tx\n",
+ printk(KERN_WARNING "%s: Inconsistent state loading while not in tx\n",
dev->name);
-#endif
-#ifdef BLOCKOUT_3
- lp->loading=2; /* So we can spot loading interruptions */
-#endif
if (dev->tbusy)
{
@@ -529,21 +524,22 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
int txsr = inb(TX_STATUS);
-#ifdef BLOCKOUT_2
+
if(lp->loading==1)
{
if(el_debug > 2)
{
- printk("%s: Interrupt while loading [", dev->name);
+ printk(KERN_DEBUG "%s: Interrupt while loading [", dev->name);
printk(" txsr=%02x gp=%04x rp=%04x]\n", txsr, inw(GP_LOW),inw(RX_LOW));
}
lp->loading=2; /* Force a reload */
dev->interrupt = 0;
+ spin_unlock(&lp->lock);
return;
}
-#endif
+
if (el_debug > 6)
- printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW));
+ printk(KERN_DEBUG " txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),inw(RX_LOW));
if ((axsr & 0x80) && (txsr & TX_READY) == 0)
{
@@ -585,6 +581,7 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outb(AX_XMIT, AX_CMD);
lp->stats.collisions++;
dev->interrupt = 0;
+ spin_unlock(&lp->lock);
return;
}
else
@@ -654,6 +651,7 @@ static void el_interrupt(int irq, void *dev_id, struct pt_regs *regs)
inb(RX_STATUS); /* Be certain that interrupts are cleared. */
inb(TX_STATUS);
dev->interrupt = 0;
+ spin_unlock(&lp->lock);
return;
}
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 75a2e37ad..9f922c43e 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -684,7 +684,6 @@ cleanup_module(void)
void *priv = dev->priv;
/* NB: el2_close() handles free_irq */
release_region(dev->base_addr, EL2_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index b8e9936f8..34edf2200 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -266,12 +266,12 @@ static inline unsigned int backlog_next(unsigned int n)
static inline int get_status(unsigned int base_addr)
{
- int timeout = jiffies + 10;
+ int timeout = jiffies + 10*HZ/100;
register int stat1;
do {
stat1 = inb_status(base_addr);
- } while (stat1 != inb_status(base_addr) && jiffies < timeout);
- if (jiffies >= timeout)
+ } while (stat1 != inb_status(base_addr) && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout))
TIMEOUT_MSG(__LINE__);
return stat1;
}
@@ -296,23 +296,23 @@ inline static void adapter_reset(struct device *dev)
if (inb_status(dev->base_addr) & ACRF) {
do {
inb_command(dev->base_addr);
- timeout = jiffies + 2;
- while ((jiffies <= timeout) && !(inb_status(dev->base_addr) & ACRF));
+ timeout = jiffies + 2*HZ/100;
+ while (time_before_eq(jiffies, timeout) && !(inb_status(dev->base_addr) & ACRF));
} while (inb_status(dev->base_addr) & ACRF);
set_hsf(dev, HSF_PCB_NAK);
}
outb_control(adapter->hcr_val | ATTN | DIR, dev);
- timeout = jiffies + 1;
- while (jiffies <= timeout);
+ timeout = jiffies + 1*HZ/100;
+ while (time_before_eq(jiffies, timeout));
outb_control(adapter->hcr_val & ~ATTN, dev);
- timeout = jiffies + 1;
- while (jiffies <= timeout);
+ timeout = jiffies + 1*HZ/100;
+ while (time_before_eq(jiffies, timeout));
outb_control(adapter->hcr_val | FLSH, dev);
- timeout = jiffies + 1;
- while (jiffies <= timeout);
+ timeout = jiffies + 1*HZ/100;
+ while (time_before_eq(jiffies, timeout));
outb_control(adapter->hcr_val & ~FLSH, dev);
- timeout = jiffies + 1;
- while (jiffies <= timeout);
+ timeout = jiffies + 1*HZ/100;
+ while (time_before_eq(jiffies, timeout));
outb_control(orig_hcr, dev);
if (!start_receive(dev, &adapter->tx_pcb))
@@ -326,7 +326,7 @@ inline static void adapter_reset(struct device *dev)
static inline void check_3c505_dma(struct device *dev)
{
elp_device *adapter = dev->priv;
- if (adapter->dmaing && (jiffies > (adapter->current_dma.start_time + 10))) {
+ if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
unsigned long flags, f;
printk("%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
save_flags(flags);
@@ -350,7 +350,7 @@ static inline unsigned int send_pcb_slow(unsigned int base_addr, unsigned char b
{
unsigned int timeout;
outb_command(byte, base_addr);
- for (timeout = jiffies + 5; jiffies < timeout;) {
+ for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
if (inb_status(base_addr) & HCRE)
return FALSE;
}
@@ -448,7 +448,7 @@ static int send_pcb(struct device *dev, pcb_struct * pcb)
/* now wait for the acknowledgement */
sti();
- for (timeout = jiffies + 5; jiffies < timeout;) {
+ for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
switch (GET_ASF(dev->base_addr)) {
case ASF_PCB_ACK:
adapter->send_pcb_semaphore = 0;
@@ -499,18 +499,18 @@ static int receive_pcb(struct device *dev, pcb_struct * pcb)
set_hsf(dev, 0);
/* get the command code */
- timeout = jiffies + 2;
- while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout);
- if (jiffies >= timeout) {
+ timeout = jiffies + 2*HZ/100;
+ while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout)) {
TIMEOUT_MSG(__LINE__);
return FALSE;
}
pcb->command = inb_command(dev->base_addr);
/* read the data length */
- timeout = jiffies + 3;
- while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout);
- if (jiffies >= timeout) {
+ timeout = jiffies + 3*HZ/100;
+ while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout)) {
TIMEOUT_MSG(__LINE__);
printk("%s: status %02x\n", dev->name, stat);
return FALSE;
@@ -738,8 +738,8 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
/*
* receive a PCB from the adapter
*/
- timeout = jiffies + 3;
- while ((inb_status(dev->base_addr) & ACRF) != 0 && jiffies < timeout) {
+ timeout = jiffies + 3*HZ/100;
+ while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {
if (receive_pcb(dev, &adapter->irx_pcb)) {
switch (adapter->irx_pcb.command) {
case 0:
@@ -971,8 +971,8 @@ static int elp_open(struct device *dev)
printk("%s: couldn't send memory configuration command\n", dev->name);
else {
int timeout = jiffies + TIMEOUT;
- while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && jiffies < timeout);
- if (jiffies >= timeout)
+ while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout))
TIMEOUT_MSG(__LINE__);
}
@@ -990,8 +990,8 @@ static int elp_open(struct device *dev)
printk("%s: couldn't send 82586 configure command\n", dev->name);
else {
int timeout = jiffies + TIMEOUT;
- while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout);
- if (jiffies >= timeout)
+ while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout))
TIMEOUT_MSG(__LINE__);
}
@@ -1177,8 +1177,8 @@ static struct net_device_stats *elp_get_stats(struct device *dev)
printk("%s: couldn't send get statistics command\n", dev->name);
else {
int timeout = jiffies + TIMEOUT;
- while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && jiffies < timeout);
- if (jiffies >= timeout) {
+ while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout)) {
TIMEOUT_MSG(__LINE__);
return &adapter->stats;
}
@@ -1270,8 +1270,8 @@ static void elp_set_mc_list(struct device *dev)
printk("%s: couldn't send set_multicast command\n", dev->name);
else {
int timeout = jiffies + TIMEOUT;
- while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout);
- if (jiffies >= timeout) {
+ while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout)) {
TIMEOUT_MSG(__LINE__);
}
}
@@ -1294,8 +1294,8 @@ static void elp_set_mc_list(struct device *dev)
printk("%s: couldn't send 82586 configure command\n", dev->name);
else {
int timeout = jiffies + TIMEOUT;
- while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout);
- if (jiffies >= timeout)
+ while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
+ if (time_after_eq(jiffies, timeout))
TIMEOUT_MSG(__LINE__);
}
}
@@ -1371,8 +1371,8 @@ __initfunc(static int elp_sense(struct device *dev))
if (orig_HSR & DIR) {
/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
outb(0, dev->base_addr + PORT_CONTROL);
- timeout = jiffies + 30;
- while (jiffies < timeout);
+ timeout = jiffies + 30*HZ/100;
+ while (time_before(jiffies, timeout));
restore_flags(flags);
if (inb_status(addr) & DIR) {
if (elp_debug > 0)
@@ -1382,8 +1382,8 @@ __initfunc(static int elp_sense(struct device *dev))
} else {
/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
outb(DIR, dev->base_addr + PORT_CONTROL);
- timeout = jiffies + 30;
- while (jiffies < timeout);
+ timeout = jiffies + 30*HZ/100;
+ while (time_before(jiffies, timeout));
restore_flags(flags);
if (!(inb_status(addr) & DIR)) {
if (elp_debug > 0)
@@ -1479,13 +1479,13 @@ __initfunc(int elplus_probe(struct device *dev))
/* First try to write just one byte, to see if the card is
* responding at all normally.
*/
- timeout = jiffies + 5;
+ timeout = jiffies + 5*HZ/100;
okay = 0;
- while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE));
+ while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
if ((inb_status(dev->base_addr) & HCRE)) {
outb_command(0, dev->base_addr); /* send a spurious byte */
- timeout = jiffies + 5;
- while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE));
+ timeout = jiffies + 5*HZ/100;
+ while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
if (inb_status(dev->base_addr) & HCRE)
okay = 1;
}
@@ -1499,8 +1499,8 @@ __initfunc(int elplus_probe(struct device *dev))
* Give it the benefit of the doubt for 10 seconds.
*/
printk("assuming 3c505 still starting\n");
- timeout = jiffies + 10 * HZ;
- while (jiffies < timeout && (inb_status(dev->base_addr) & 7));
+ timeout = jiffies + 10*HZ;
+ while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7));
if (inb_status(dev->base_addr) & 7) {
printk("%s: 3c505 failed to start\n", dev->name);
} else {
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index 58a44182e..2b79709aa 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -63,6 +63,7 @@ static char *version = "3c509.c:1.12 6/4/97 becker@cesdis.gsfc.nasa.gov\n";
#include <asm/spinlock.h>
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/irq.h>
#ifdef EL3_DEBUG
int el3_debug = EL3_DEBUG;
@@ -407,7 +408,7 @@ el3_open(struct device *dev)
/* Set the spinlock before grabbing IRQ! */
((struct el3_private *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
- if (request_irq(dev->irq, &el3_interrupt, 0, "3c509", dev)) {
+ if (request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev)) {
return -EAGAIN;
}
@@ -526,10 +527,21 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
printk("%s: Transmitter access conflict.\n", dev->name);
else {
- unsigned long flags;
-
- /* Spin on the lock, until we're clear of an IRQ */
- spin_lock_irqsave(&lp->lock, flags);
+ /*
+ * We lock the driver against other processors. Note
+ * we don't need to lock versus the IRQ as we suspended
+ * that. This means that we lose the ability to take
+ * an RX during a TX upload. That sucks a bit with SMP
+ * on an original 3c509 (2K buffer)
+ *
+ * Using disable_irq stops us crapping on other
+ * time sensitive devices.
+ */
+
+#ifdef __SMP__
+ disable_irq(dev->irq);
+ spin_lock(&lp->lock);
+#endif
/* Put out the doubleword header... */
outw(skb->len, ioaddr + TX_FIFO);
@@ -547,8 +559,10 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
} else
/* Interrupt us when the FIFO has room for max-sized packet. */
outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
-
- spin_unlock_irqrestore(&lp->lock, flags);
+#ifdef __SMP__
+ spin_unlock(&lp->lock);
+ enable_irq(dev->irq);
+#endif
}
dev_kfree_skb (skb);
@@ -658,10 +672,14 @@ el3_get_stats(struct device *dev)
struct el3_private *lp = (struct el3_private *)dev->priv;
unsigned long flags;
- save_flags(flags);
- cli();
+ /*
+ * This is fast enough not to bother with disable IRQ
+ * stuff.
+ */
+
+ spin_lock_irqsave(&lp->lock, flags);
update_stats(dev);
- restore_flags(flags);
+ spin_unlock_irqrestore(&lp->lock, flags);
return &lp->stats;
}
@@ -683,13 +701,13 @@ static void update_stats(struct device *dev)
EL3WINDOW(6);
lp->stats.tx_carrier_errors += inb(ioaddr + 0);
lp->stats.tx_heartbeat_errors += inb(ioaddr + 1);
- /* Multiple collisions. */ inb(ioaddr + 2);
- lp->stats.collisions += inb(ioaddr + 3);
- lp->stats.tx_window_errors += inb(ioaddr + 4);
- lp->stats.rx_fifo_errors += inb(ioaddr + 5);
- lp->stats.tx_packets += inb(ioaddr + 6);
- /* Rx packets */ inb(ioaddr + 7);
- /* Tx deferrals */ inb(ioaddr + 8);
+ /* Multiple collisions. */ inb(ioaddr + 2);
+ lp->stats.collisions += inb(ioaddr + 3);
+ lp->stats.tx_window_errors += inb(ioaddr + 4);
+ lp->stats.rx_fifo_errors += inb(ioaddr + 5);
+ lp->stats.tx_packets += inb(ioaddr + 6);
+ /* Rx packets */ inb(ioaddr + 7);
+ /* Tx deferrals */ inb(ioaddr + 8);
inw(ioaddr + 10); /* Total Rx and Tx octets. */
inw(ioaddr + 12);
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index b74ca51e6..7dc831e58 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -39,16 +39,8 @@ static int max_interrupt_work = 20;
#define RX_RING_SIZE 16
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -67,12 +59,9 @@ static int max_interrupt_work = 20;
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-#if (LINUX_VERSION_CODE >= 0x10344)
+
#define NEW_MULTICAST
#include <linux/delay.h>
-#else
-#define udelay(microsec) do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
/* Kernel version compatibility functions. */
#define RUN_AT(x) (jiffies + (x))
@@ -758,7 +747,7 @@ vortex_open(struct device *dev)
vp->tx_skbuff[i] = 0;
outl(0, ioaddr + DownListPtr);
}
- /* Set reciever mode: presumably accept b-case and phys addr only. */
+ /* Set receiver mode: presumably accept b-case and phys addr only. */
set_rx_mode(dev);
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index 968168d01..d907fe7f3 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -184,7 +184,7 @@ static void set_multicast_list(struct device *dev);
/* helper-functions */
static int init586(struct device *dev);
-static int check586(struct device *dev, char *where, unsigned size);
+static int check586(struct device *dev, unsigned long where, unsigned size);
static void alloc586(struct device *dev);
static void startrecv586(struct device *dev);
static void *alloc_rfa(struct device *dev, void *ptr);
@@ -311,19 +311,19 @@ static int elmc_open(struct device *dev)
* Check to see if there's an 82586 out there.
*/
-__initfunc(static int check586(struct device *dev, char *where, unsigned size))
+__initfunc(static int check586(struct device *dev, unsigned long where, unsigned size))
{
struct priv *p = (struct priv *) dev->priv;
char *iscp_addrs[2];
int i = 0;
- p->base = (unsigned long) where + size - 0x01000000;
- p->memtop = where + size;
- p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+ p->base = where + size - 0x01000000;
+ p->memtop = phys_to_virt(where) + size;
+ p->scp = (struct scp_struct *)phys_to_virt(p->base + SCP_DEFAULT_ADDRESS);
memset((char *) p->scp, 0, sizeof(struct scp_struct));
p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */
- iscp_addrs[0] = where;
+ iscp_addrs[0] = phys_to_virt(where);
iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
for (i = 0; i < 2; i++) {
@@ -358,8 +358,8 @@ void alloc586(struct device *dev)
elmc_id_reset586();
DELAY(2);
- p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
- p->scb = (struct scb_struct *) (dev->mem_start);
+ p->scp = (struct scp_struct *) phys_to_virt(p->base + SCP_DEFAULT_ADDRESS);
+ p->scb = (struct scb_struct *) phys_to_virt(dev->mem_start);
p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
@@ -521,9 +521,9 @@ __initfunc(int elmc_probe(struct device *dev))
/* The 3c523 has a 24K chunk of memory. The first 16K is the
shared memory, while the last 8K is for the EtherStart BIOS ROM.
Which we don't care much about here. We'll just tell Linux that
- we're using 16K. MCA won't permit adress space conflicts caused
+ we're using 16K. MCA won't permit address space conflicts caused
by not mapping the other 8K. */
- dev->mem_start = phys_to_virt(shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]);
+ dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];
/* We're using MCA, so it's a given that the information about memory
size is correct. The Crynwr drivers do something like this. */
@@ -531,7 +531,7 @@ __initfunc(int elmc_probe(struct device *dev))
elmc_id_reset586(); /* seems like a good idea before checking it... */
size = 0x4000; /* check for 16K mem */
- if (!check586(dev, (char *) dev->mem_start, size)) {
+ if (!check586(dev, dev->mem_start, size)) {
printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
dev->mem_start);
release_region(dev->base_addr, ELMC_IO_EXTENT);
@@ -550,8 +550,7 @@ __initfunc(int elmc_probe(struct device *dev))
/* dump all the assorted information */
printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
dev->irq, dev->if_port ? "ex" : "in",
- virt_to_phys(dev->mem_start),
- virt_to_phys(dev->mem_end - 1));
+ dev->mem_start, dev->mem_end - 1);
/* The hardware address for the 3c523 is stored in the first six
bytes of the IO address. */
@@ -628,7 +627,7 @@ static int init586(struct device *dev)
s = jiffies; /* warning: only active with interrupts on !! */
while (!(cfg_cmd->cmd_status & STAT_COMPL)) {
- if (jiffies - s > 30)
+ if (jiffies - s > 30*HZ/100)
break;
}
@@ -654,7 +653,7 @@ static int init586(struct device *dev)
s = jiffies;
while (!(ias_cmd->cmd_status & STAT_COMPL)) {
- if (jiffies - s > 30)
+ if (jiffies - s > 30*HZ/100)
break;
}
@@ -679,7 +678,7 @@ static int init586(struct device *dev)
s = jiffies;
while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
- if (jiffies - s > 30) {
+ if (jiffies - s > 30*HZ/100) {
printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
result = 1;
break;
@@ -768,7 +767,7 @@ static int init586(struct device *dev)
elmc_id_attn586();
s = jiffies;
while (!(mc_cmd->cmd_status & STAT_COMPL)) {
- if (jiffies - s > 30)
+ if (jiffies - s > 30*HZ/100)
break;
}
if (!(mc_cmd->cmd_status & STAT_COMPL)) {
@@ -964,7 +963,7 @@ static void elmc_rcv_int(struct device *dev)
if (skb != NULL) {
skb->dev = dev;
skb_reserve(skb, 2); /* 16 byte alignment */
- memcpy(skb_put(skb, totlen), (char *) p->base + (unsigned long) rbd->buffer, totlen);
+ memcpy(skb_put(skb, totlen), (u8 *)phys_to_virt(p->base) + (unsigned long) rbd->buffer, totlen);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
p->stats.rx_packets++;
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 547d0497c..62f73cd71 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -15,18 +15,19 @@
*/
static char *version =
-"3c59x.c:v0.99E 5/12/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
-static const rx_copybreak = 200;
+static const int rx_copybreak = 200;
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
-static const mtu = 1500;
+static const int mtu = 1500;
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 20;
/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
+#define vortex_debug debug
#ifdef VORTEX_DEBUG
static int vortex_debug = VORTEX_DEBUG;
#else
@@ -37,15 +38,6 @@ static int vortex_debug = 1;
debugging. */
static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
-/* Enable the automatic media selection code -- usually set. */
-#define AUTOMEDIA 1
-
-/* Allow the use of fragment bus master transfers instead of only
- programmed-I/O for Vortex cards. Full-bus-master transfers are always
- enabled by default on Boomerang cards. If VORTEX_BUS_MASTER is defined,
- the feature may be turned on using 'options'. */
-#define VORTEX_BUS_MASTER
-
/* A few values that may be tweaked. */
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT ((400*HZ)/1000)
@@ -56,12 +48,12 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
#include <linux/config.h>
+#include <linux/version.h>
#ifdef MODULE
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>
-#include <linux/version.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
@@ -70,41 +62,51 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/ptrace.h>
+#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/timer.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h> /* For NR_IRQS only. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS)
+#include <linux/bios32.h>
+#endif
+#include <asm/irq.h> /* For NR_IRQS only. */
+#include <asm/bitops.h>
+#include <asm/io.h>
-/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
This is only in the support-all-kernels source code. */
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h> /* Redundant above, here for easy clean-up. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+#include <linux/delay.h>
+
+#if (LINUX_VERSION_CODE <= 0x20100)
+#ifndef __alpha__
+#define ioremap(a,b) \
+ (((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
+#define iounmap(v) \
+ do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
#endif
-#if LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x) /* What to put in timer->expires. */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#if defined(__alpha)
-#error "The Alpha architecture is only support with kernel version 2.0."
#endif
-#define virt_to_bus(addr) ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-#define NR_IRQS 16
-#else /* 1.3.0 and later */
-#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len)
+#if LINUX_VERSION_CODE <= 0x20139
+#define net_device_stats enet_statistics
+#define NETSTATS_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20138
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#define le32_to_cpu(val) (val)
+#define cpu_to_le32(val) (val)
+#endif
+#if LINUX_VERSION_CODE < 0x20155
+#define PCI_SUPPORT_VER1
+#else
+#define PCI_SUPPORT_VER2
#endif
#if LINUX_VERSION_CODE < 0x20159
#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
@@ -112,27 +114,7 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
#endif
-#ifdef SA_SHIRQ
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#else
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
-#endif
-
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
-#include <linux/delay.h>
-#else
-#define udelay(microsec) do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
-
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
MODULE_PARM(debug, "i");
@@ -142,7 +124,7 @@ MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
-MODULE_PARM(compaq_prod_id, "i");
+MODULE_PARM(compaq_device_id, "i");
#endif
/* Operational parameter that usually are not changed. */
@@ -154,35 +136,11 @@ MODULE_PARM(compaq_prod_id, "i");
#define VORTEX_TOTAL_SIZE 0x20
#define BOOMERANG_TOTAL_SIZE 0x40
-#ifdef HAVE_DEVLIST
-struct netdev_entry tc59x_drv =
-{"Vortex", vortex_pci_probe, VORTEX_TOTAL_SIZE, NULL};
-#endif
-
/* Set iff a MII transceiver on any interface requires mdio preamble.
This only set with the original DP83840 on older 3c905 boards, so the extra
code size of a per-interface flag is not worthwhile. */
static char mii_preamble_required = 0;
-/* Caution! These entries must be consistent. */
-static const int product_ids[] = {
- 0x5900, 0x5920, 0x5970, 0x5950, 0x5951, 0x5952, 0x9000, 0x9001,
- 0x9050, 0x9051, 0x9055, 0x5057, 0 };
-static const char *product_names[] = {
- "3c590 Vortex 10Mbps",
- "3c592 EISA 10mbps Demon/Vortex",
- "3c597 EISA Fast Demon/Vortex",
- "3c595 Vortex 100baseTX",
- "3c595 Vortex 100baseT4",
- "3c595 Vortex 100base-MII",
- "3c900 Boomerang 10baseT",
- "3c900 Boomerang 10Mbps/Combo",
- "3c905 Boomerang 100baseTx",
- "3c905 Boomerang 100baseT4",
- "3c905B Cyclone 100baseTx",
- "3c575", /* Cardbus Boomerang */
-};
-
/*
Theory of Operation
@@ -193,17 +151,19 @@ XL, 3Com's PCI to 10/100baseT adapters. It also works with the 10Mbs
versions of the FastEtherLink cards. The supported product IDs are
3c590, 3c592, 3c595, 3c597, 3c900, 3c905
-The ISA 3c515 is supported with a seperate driver, 3c515.c, included with
-the kernel source or available from
+The related ISA 3c515 is supported with a separate driver, 3c515.c, included
+with the kernel source or available from
cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
II. Board-specific settings
PCI bus devices are configured by the system at boot time, so no jumpers
need to be set on the board. The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line. While it's
-physically possible to shared PCI interrupt lines, the 1.2.0 kernel doesn't
-support it.
+PCI INTA signal to an otherwise unused system IRQ line.
+
+The EEPROM settings for media type and forced-full-duplex are observed.
+The EEPROM media type should be left at the default "autoselect" unless using
+10base2 or AUI connections which cannot be reliably detected.
III. Driver operation
@@ -211,10 +171,10 @@ The 3c59x series use an interface that's very similar to the previous 3c5x9
series. The primary interface is two programmed-I/O FIFOs, with an
alternate single-contiguous-region bus-master transfer (see next).
-The 3c900 "Boomerang" series uses a full-bus-master interface with seperate
+The 3c900 "Boomerang" series uses a full-bus-master interface with separate
lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
DEC Tulip and Intel Speedo3. The first chip version retains a compatible
-programmed-I/O interface that will be removed in the 'B' and subsequent
+programmed-I/O interface that has been removed in 'B' and subsequent board
revisions.
One extension that is advertised in a very large font is that the adapters
@@ -232,7 +192,7 @@ packets may be reordered and receive buffer groups are associated with a
single frame.
With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme.
-Tather than a fixed intermediate receive buffer, this scheme allocates
+Rather than a fixed intermediate receive buffer, this scheme allocates
full-sized skbuffs as receive buffers. The value RX_COPYBREAK is used as
the copying breakpoint: it is chosen to trade-off the memory wasted by
passing the full-sized skbuff to the queue layer for all frames vs. the
@@ -258,7 +218,66 @@ This driver only supports ethernet packets because of the skbuff allocation
limit of 4K.
*/
-#define TCOM_VENDOR_ID 0x10B7 /* 3Com's manufacturer's ID. */
+/* This table drives the PCI probe routines. It's mostly boilerplate in all
+ of the drivers, and will likely be provided by some future kernel.
+*/
+enum pci_flags_bit {
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+ const char *name;
+ u16 vendor_id, device_id, device_id_mask, flags;
+ int drv_flags, io_size;
+ struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+ long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+
+enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
+ HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
+static struct device *vortex_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr,
+ int irq, int dev_id, int card_idx);
+static struct pci_id_info pci_tbl[] = {
+ {"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3c595 Vortex 100baseTx", 0x10B7, 0x5950, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3c595 Vortex 100baseT4", 0x10B7, 0x5951, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3c595 Vortex 100base-MII", 0x10B7, 0x5952, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3Com Vortex", 0x10B7, 0x5900, 0xff00,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {"3c900 Boomerang 10baseT", 0x10B7, 0x9000, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {"3c900 Boomerang 10Mbps Combo", 0x10B7, 0x9001, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {"3c900 Cyclone 10Mbps Combo", 0x10B7, 0x9005, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c900B-FL Cyclone 10base-FL", 0x10B7, 0x900A, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c905 Boomerang 100baseTx", 0x10B7, 0x9050, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3c905 Boomerang 100baseT4", 0x10B7, 0x9051, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3c905B Cyclone 100baseTx", 0x10B7, 0x9055, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
+ {"3c905B-FX Cyclone 100baseFx", 0x10B7, 0x905A, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c980 Cyclone", 0x10B7, 0x9800, 0xfff0,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c575 Boomerang CardBus", 0x10B7, 0x5057, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3CCFE575 Cyclone CardBus", 0x10B7, 0x5157, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+ 128, vortex_probe1},
+ {"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3Com Boomerang (unknown version)", 0x10B7, 0x9000, 0xff00,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {0,}, /* 0 terminated list. */
+};
/* Operational definitions.
These are not used by other compilation units and thus are not
@@ -287,7 +306,7 @@ enum vortex_cmd {
SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
SetTxThreshold = 18<<11, SetTxStart = 19<<11,
StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
- StatsDisable = 22<<11, StopCoax = 23<<11,};
+ StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,};
/* The SetRxFilter command accepts the following classes: */
enum RxFilter {
@@ -327,26 +346,19 @@ enum eeprom_offset {
NodeAddr01=10, NodeAddr23=11, NodeAddr45=12,
DriverTune=13, Checksum=15};
+enum Window2 { /* Window 2. */
+ Wn2_ResetOptions=12,
+};
enum Window3 { /* Window 3: MAC/config bits. */
Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
};
union wn3_config {
int i;
struct w3_config_fields {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
int pad8:8;
unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
int pad24:7;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned int rom_size:2, ram_speed:2, ram_width:1, ram_size:3;
- int pad8:8;
- unsigned int xcvr:4, pad18:2, ram_split:2;
- int pad24:7;
- unsigned int autoselect:1;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
} u;
};
@@ -404,37 +416,37 @@ enum tx_desc_status {
enum ChipCaps { CapBusMaster=0x20 };
struct vortex_private {
- char devname[8]; /* "ethN" string, also for kernel debug. */
- const char *product_name;
- struct device *next_module;
- /* The Rx and Tx rings are here to keep them quad-word-aligned. */
+ /* The Rx and Tx rings should be quad-word-aligned. */
struct boom_rx_desc rx_ring[RX_RING_SIZE];
struct boom_tx_desc tx_ring[TX_RING_SIZE];
/* The addresses of transmit- and receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ struct device *next_module;
+ void *priv_addr;
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
- struct enet_statistics stats;
+ struct net_device_stats stats;
struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
/* PCI configuration space information. */
- u8 pci_bus, pci_dev_fn; /* PCI bus location, for power management. */
- u16 pci_device_id;
+ u8 pci_bus, pci_devfn; /* PCI bus location, for power management. */
+ char *cb_fn_base; /* CardBus function status addr space. */
+ int chip_id;
/* The remainder are related to chip state, mostly media selection. */
- int in_interrupt;
+ unsigned long in_interrupt;
struct timer_list timer; /* Media selection timer. */
int options; /* User-settable misc. driver options. */
- unsigned int
- media_override:3, /* Passed-in media type. */
- default_media:3, /* Read from the EEPROM/Wn3_Config. */
- full_duplex:1, autoselect:1,
- bus_master:1, /* Vortex can only do a fragment bus-m. */
- full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
- hw_csums:1, /* Has hardware checksums. */
- tx_full:1;
+ unsigned int media_override:3, /* Passed-in media type. */
+ default_media:4, /* Read from the EEPROM/Wn3_Config. */
+ full_duplex:1, force_fd:1, autoselect:1,
+ bus_master:1, /* Vortex can only do a fragment bus-m. */
+ full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
+ hw_csums:1, /* Has hardware checksums. */
+ tx_full:1;
u16 status_enable;
+ u16 intr_enable;
u16 available_media; /* From Wn3_Options. */
u16 capabilities, info1, info2; /* Various, from EEPROM. */
u16 advertising; /* NWay media advertisement */
@@ -469,61 +481,39 @@ static struct media_table {
{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
};
-static int vortex_scan(struct device *dev);
-static struct device *vortex_found_device(struct device *dev, int ioaddr,
- int irq, int device_id,
- int options, int card_idx);
-static int vortex_probe1(struct device *dev);
-static int vortex_open(struct device *dev);
-static void mdio_sync(int ioaddr, int bits);
-static int mdio_read(int ioaddr, int phy_id, int location);
-#ifdef HAVE_PRIVATE_IOCTL
-static void mdio_write(int ioaddr, int phy_id, int location, int value);
+#ifndef CARDBUS
+static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[]);
#endif
+static int vortex_open(struct device *dev);
+static void mdio_sync(long ioaddr, int bits);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
static void vortex_timer(unsigned long arg);
static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
static int boomerang_start_xmit(struct sk_buff *skb, struct device *dev);
static int vortex_rx(struct device *dev);
static int boomerang_rx(struct device *dev);
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs);
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct device *dev);
-static void update_stats(int addr, struct device *dev);
-static struct enet_statistics *vortex_get_stats(struct device *dev);
+static void update_stats(long ioaddr, struct device *dev);
+static struct net_device_stats *vortex_get_stats(struct device *dev);
static void set_rx_mode(struct device *dev);
-#ifdef HAVE_PRIVATE_IOCTL
static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-#endif
-#ifndef NEW_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
-/* Unlike the other PCI cards the 59x cards don't need a large contiguous
- memory region, so making the driver a loadable module is feasible.
-
- Unfortunately maximizing the shared code between the integrated and
- module version of the driver results in a complicated set of initialization
- procedures.
- init_module() -- modules / tc59x_init() -- built-in
- The wrappers for vortex_scan()
- vortex_scan() The common routine that scans for PCI and EISA cards
- vortex_found_device() Allocate a device structure when we find a card.
- Different versions exist for modules and built-in.
- vortex_probe1() Fill in the device structure -- this is separated
- so that the modules code can put it in dev->init.
-*/
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
-/* Note: this is the only limit on the number of cards supported!! */
-static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
-static int full_duplex[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Option count limit only -- unlimited interfaces are supported. */
+#define MAX_UNITS 8
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* A list of all installed Vortex devices, for removing the driver module. */
static struct device *root_vortex_dev = NULL;
#ifdef MODULE
+#ifndef CARDBUS
/* Variables to work-around the Compaq PCI BIOS32 problem. */
static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
-
-static int debug = -1;
+#endif
#ifdef CARDBUS
@@ -531,19 +521,38 @@ static int debug = -1;
static dev_node_t *vortex_attach(dev_locator_t *loc)
{
- u16 dev_id;
+ u16 dev_id, vendor_id;
u32 io;
u8 bus, devfn, irq;
struct device *dev;
+ int chip_idx;
if (loc->bus != LOC_PCI) return NULL;
bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
- printk(KERN_INFO "vortex_attach(bus %d, function %d)\n", bus, devfn);
pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+ pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
+ bus, devfn, dev_id);
io &= ~3;
- dev = vortex_found_device(NULL, io, irq, dev_id, 0, -1);
+ if (io == 0 || irq == 0) {
+ printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
+ "assigned an %s.\n" KERN_ERR " It will not be activated.\n",
+ io == 0 ? "I/O address" : "IRQ");
+ return NULL;
+ }
+ for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor_id == pci_tbl[chip_idx].vendor_id
+ && (dev_id & pci_tbl[chip_idx].device_id_mask) ==
+ pci_tbl[chip_idx].device_id)
+ break;
+ if (pci_tbl[chip_idx].vendor_id == 0) { /* Compiled out! */
+ printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "
+ "vortex_attach().\n", vendor_id, dev_id);
+ return NULL;
+ }
+ dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
if (dev) {
dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
strcpy(node->dev_name, dev->name);
@@ -565,61 +574,52 @@ static void vortex_detach(dev_node_t *node)
}
if (*devp) {
struct device *dev = *devp;
+ struct vortex_private *vp = dev->priv;
if (dev->flags & IFF_UP)
vortex_close(dev);
dev->flags &= ~(IFF_UP|IFF_RUNNING);
unregister_netdev(dev);
+ if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
kfree(dev);
*devp = *next;
+ kfree(vp);
kfree(node);
MOD_DEC_USE_COUNT;
}
}
struct driver_operations vortex_ops = {
- "3c59x_cb", vortex_attach, NULL, NULL, vortex_detach
+ "3c575_cb", vortex_attach, NULL, NULL, vortex_detach
};
#endif /* Cardbus support */
-int
-init_module(void)
+int init_module(void)
{
- if (debug >= 0)
- vortex_debug = debug;
if (vortex_debug)
- printk(version);
-
- root_vortex_dev = NULL;
+ printk(KERN_INFO "%s", version);
#ifdef CARDBUS
register_driver(&vortex_ops);
return 0;
#else
- {
- int cards_found = vortex_scan(0);
- if (cards_found == 0)
- printk("No 3Com Vortex/Boomerang cards found.\n");
- return cards_found ? 0 : -ENODEV;
- }
+ return vortex_scan(0, pci_tbl);
#endif
}
#else
int tc59x_probe(struct device *dev)
{
- int cards_found = 0;
-
- cards_found = vortex_scan(dev);
-
- if (vortex_debug > 0 && cards_found)
- printk(version);
-
- return cards_found ? 0 : -ENODEV;
+ static int scanned=0;
+ if(scanned++)
+ return -ENODEV;
+ printk(KERN_INFO "%s", version);
+ return vortex_scan(dev, pci_tbl);
}
#endif /* not MODULE */
-static int vortex_scan(struct device *dev)
+#ifndef CARDBUS
+static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[])
{
int cards_found = 0;
@@ -634,25 +634,30 @@ static int vortex_scan(struct device *dev)
unsigned char pci_bus, pci_device_fn;
for (;pci_index < 0xff; pci_index++) {
- u8 pci_latency;
- u16 pci_command, new_command, vendor, device;
- int irq;
+ u16 vendor, device, pci_command, new_command, pwr_cmd;
+ int chip_idx, irq;
long ioaddr;
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
- pci_index, &pci_bus, &pci_device_fn)
+ if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
+ &pci_bus, &pci_device_fn)
!= PCIBIOS_SUCCESSFUL)
break;
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_VENDOR_ID, &vendor);
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_DEVICE_ID, &device);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor == pci_tbl[chip_idx].vendor_id
+ && (device & pci_tbl[chip_idx].device_id_mask) ==
+ pci_tbl[chip_idx].device_id)
+ break;
+ if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
+ continue;
+
{
#if LINUX_VERSION_CODE >= 0x20155
struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->base_address[0];
+ ioaddr = pdev->base_address[0] & ~3;
irq = pdev->irq;
#else
u32 pci_ioaddr;
@@ -661,15 +666,28 @@ static int vortex_scan(struct device *dev)
PCI_INTERRUPT_LINE, &pci_irq_line);
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &pci_ioaddr);
- ioaddr = pci_ioaddr;
+ ioaddr = pci_ioaddr & ~3;;
irq = pci_irq_line;
#endif
}
- /* Remove I/O space marker in bit 0. */
- ioaddr &= ~3;
- if (vendor != TCOM_VENDOR_ID)
- continue;
+ /* Power-up the card. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ 0xe0, &pwr_cmd);
+ if (pwr_cmd & 0x3) {
+ /* Save the ioaddr and IRQ info! */
+ printk(KERN_INFO " A 3Com network adapter is powered down!"
+ " Setting the power state %4.4x->%4.4x.\n",
+ pwr_cmd, pwr_cmd & ~3);
+ pcibios_write_config_word(pci_bus, pci_device_fn,
+ 0xe0, pwr_cmd & ~3);
+ printk(KERN_INFO " Setting the IRQ to %d, IOADDR to %#lx.\n",
+ irq, ioaddr);
+ pcibios_write_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, irq);
+ pcibios_write_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, ioaddr);
+ }
if (ioaddr == 0) {
printk(KERN_WARNING " A 3Com network adapter has been found, "
@@ -679,34 +697,31 @@ static int vortex_scan(struct device *dev)
continue;
}
- if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
+ if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
continue;
/* Activate the card. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled this"
- " device! Updating PCI command %4.4x->%4.4x.\n",
- pci_command, new_command);
+ printk(KERN_INFO " The PCI BIOS has not enabled the device "
+ "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
+ pci_bus, pci_device_fn, pci_command, new_command);
pcibios_write_config_word(pci_bus, pci_device_fn,
PCI_COMMAND, new_command);
}
- dev = vortex_found_device(dev, ioaddr, irq,
- device, dev && dev->mem_start
- ? dev->mem_start : options[cards_found],
- cards_found);
+ dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq,
+ chip_idx, cards_found);
if (dev) {
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
/* Get and check the latency values. On the 3c590 series
the latency timer must be set to the maximum value to avoid
data corruption that occurs when the timer expires during
a transfer -- a bug in the Vortex chip only. */
- u8 new_latency = (device&0xff00) == 0x5900 ? 248 : 32;
- vp->pci_bus = pci_bus;
- vp->pci_dev_fn = pci_device_fn;
- vp->pci_device_id = device;
+ u8 pci_latency;
+ u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_LATENCY_TIMER, &pci_latency);
@@ -726,7 +741,7 @@ static int vortex_scan(struct device *dev)
/* Now check all slots of the EISA bus. */
if (EISA_bus) {
- static int ioaddr = 0x1000;
+ static long ioaddr = 0x1000;
for ( ; ioaddr < 0x9000; ioaddr += 0x1000) {
int device_id;
if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
@@ -738,10 +753,8 @@ static int vortex_scan(struct device *dev)
device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
if ((device_id & 0xFF00) != 0x5900)
continue;
- vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
- device_id, dev && dev->mem_start
- ? dev->mem_start : options[cards_found],
- cards_found);
+ vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
+ 4, cards_found);
dev = 0;
cards_found++;
}
@@ -750,97 +763,58 @@ static int vortex_scan(struct device *dev)
#ifdef MODULE
/* Special code to work-around the Compaq PCI BIOS32 problem. */
if (compaq_ioaddr) {
- vortex_found_device(dev, compaq_ioaddr, compaq_irq, compaq_device_id,
- dev && dev->mem_start ? dev->mem_start
- : options[cards_found], cards_found);
- cards_found++;
+ vortex_probe1(0, 0, dev, compaq_ioaddr, compaq_irq,
+ compaq_device_id, cards_found++);
dev = 0;
}
#endif
- /* 3c515 cards are now supported by the 3c515.c driver. */
-
- return cards_found;
+ return cards_found ? 0 : -ENODEV;
}
+#endif /* ! Cardbus */
-static struct device *
-vortex_found_device(struct device *dev, int ioaddr, int irq,
- int device_id, int option, int card_idx)
+static struct device *vortex_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr,
+ int irq, int chip_idx, int card_idx)
{
struct vortex_private *vp;
- const char *product_name;
- int board_index = 0;
+ int option;
+ unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
+ int i;
- for (board_index = 0; product_ids[board_index]; board_index++) {
- if (device_id == product_ids[board_index])
- break;
- }
- /* Handle products we don't recognize, but might still work with. */
- if (product_ids[board_index])
- product_name = product_names[board_index];
- else if ((device_id & 0xff00) == 0x5900)
- product_name = "3c590 Vortex";
- else if ((device_id & 0xfff0) == 0x9000)
- product_name = "3c900";
- else if ((device_id & 0xfff0) == 0x9050)
- product_name = "3c905";
- else {
- printk(KERN_WARNING "Unknown 3Com PCI ethernet adapter type %4.4x detected:"
- " not configured.\n", device_id);
- return 0;
- }
+ dev = init_etherdev(dev, 0);
-#ifdef MODULE
- /* Allocate and fill new device structure. */
- {
- int dev_size = sizeof(struct device) +
- sizeof(struct vortex_private) + 15; /* Pad for alignment */
+ printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
+ dev->name, pci_tbl[chip_idx].name, ioaddr);
- dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
- memset(dev, 0, dev_size);
- }
- /* Align the Rx and Tx ring entries. */
- dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
- vp = (struct vortex_private *)dev->priv;
- dev->name = vp->devname; /* An empty string. */
dev->base_addr = ioaddr;
dev->irq = irq;
- dev->init = vortex_probe1;
- vp->product_name = product_name;
- vp->options = option;
- if (card_idx >= 0) {
- if (full_duplex[card_idx] >= 0)
- vp->full_duplex = full_duplex[card_idx];
- } else
- vp->full_duplex = (option > 0 && (option & 0x10) ? 1 : 0);
+ dev->mtu = mtu;
- if (option > 0) {
- vp->media_override = ((option & 7) == XCVR_10baseTOnly) ?
- XCVR_10baseT : option & 7;
- vp->bus_master = (option & 16) ? 1 : 0;
- } else {
- vp->media_override = 7;
- vp->bus_master = 0;
+ /* Make certain the descriptor lists are aligned. */
+ {
+ void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
+ vp = (void *)(((long)mem + 15) & ~15);
+ vp->priv_addr = mem;
}
- ether_setup(dev);
+ memset(vp, 0, sizeof(*vp));
+ dev->priv = vp;
+
vp->next_module = root_vortex_dev;
root_vortex_dev = dev;
- if (register_netdev(dev) != 0)
- return 0;
-#else /* not a MODULE */
- if (dev) {
- /* Caution: quad-word alignment required for rings! */
- dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL);
- memset(dev->priv, 0, sizeof (struct vortex_private));
- }
- dev = init_etherdev(dev, sizeof(struct vortex_private));
- dev->base_addr = ioaddr;
- dev->irq = irq;
- dev->mtu = mtu;
- vp = (struct vortex_private *)dev->priv;
- vp->product_name = product_name;
- vp->options = option;
+ vp->chip_id = chip_idx;
+ vp->pci_bus = pci_bus;
+ vp->pci_devfn = pci_devfn;
+
+ /* The lower four bits are the media type. */
+ if (dev->mem_start)
+ option = dev->mem_start;
+ else if (card_idx < MAX_UNITS)
+ option = options[card_idx];
+ else
+ option = -1;
+
if (option >= 0) {
vp->media_override = ((option & 7) == 2) ? 0 : option & 7;
vp->full_duplex = (option & 8) ? 1 : 0;
@@ -850,22 +824,11 @@ vortex_found_device(struct device *dev, int ioaddr, int irq,
vp->full_duplex = 0;
vp->bus_master = 0;
}
+ if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+ vp->full_duplex = 1;
- vortex_probe1(dev);
-#endif /* MODULE */
- return dev;
-}
-
-static int vortex_probe1(struct device *dev)
-{
- int ioaddr = dev->base_addr;
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
- u16 *ether_addr = (u16 *)dev->dev_addr;
- unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
- int i;
-
- printk(KERN_INFO "%s: 3Com %s at %#3x,",
- dev->name, vp->product_name, ioaddr);
+ vp->force_fd = vp->full_duplex;
+ vp->options = option;
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
@@ -896,14 +859,30 @@ static int vortex_probe1(struct device *dev)
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
for (i = 0; i < 3; i++)
- ether_addr[i] = htons(eeprom[i + 10]);
+ ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
for (i = 0; i < 6; i++)
printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+#ifdef __sparc__
+ printk(", IRQ %s\n", __irq_itoa(dev->irq));
+#else
printk(", IRQ %d\n", dev->irq);
/* Tell them about an invalid IRQ. */
if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS))
printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
dev->irq);
+#endif
+
+ if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
+ u32 fn_st_addr; /* Cardbus function status space */
+ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
+ &fn_st_addr);
+ if (fn_st_addr)
+ vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
+ printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
+ " brain-damage).\n", dev->name, fn_st_addr, vp->cb_fn_base);
+ EL3WINDOW(2);
+ outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);
+ }
/* Extract our information from the EEPROM data. */
vp->info1 = eeprom[13];
@@ -929,7 +908,7 @@ static int vortex_probe1(struct device *dev)
config.u.ram_width ? "word" : "byte",
ram_split[config.u.ram_split],
config.u.autoselect ? "autoselect/" : "",
- config.u.xcvr ? "NWay Autonegotiation" :
+ config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :
media_tbl[config.u.xcvr].name);
vp->default_media = config.u.xcvr;
vp->autoselect = config.u.autoselect;
@@ -942,22 +921,24 @@ static int vortex_probe1(struct device *dev)
} else
dev->if_port = vp->default_media;
- if (dev->if_port == XCVR_MII) {
+ if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int phy, phy_idx = 0;
EL3WINDOW(4);
- for (phy = 0; phy < 32 && phy_idx < sizeof(vp->phys); phy++) {
- int mii_status;
- mdio_sync(ioaddr, 32);
- mii_status = mdio_read(ioaddr, phy, 1);
+ mii_preamble_required++;
+ mii_preamble_required++;
+ mdio_read(ioaddr, 24, 1);
+ for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
+ int mii_status, phyx = phy & 0x1f;
+ mii_status = mdio_read(ioaddr, phyx, 1);
if (mii_status && mii_status != 0xffff) {
- vp->phys[phy_idx++] = phy;
- printk(KERN_INFO " MII transceiver found at address %d, status %4x.\n",
- phy, mii_status);
- mdio_sync(ioaddr, 32);
- if ((mdio_read(ioaddr, phy, 1) & 0x0040) == 0)
- mii_preamble_required = 1;
+ vp->phys[phy_idx++] = phyx;
+ printk(KERN_INFO " MII transceiver found at address %d,"
+ " status %4x.\n", phyx, mii_status);
+ if ((mii_status & 0x0040) == 0)
+ mii_preamble_required++;
}
}
+ mii_preamble_required--;
if (phy_idx == 0) {
printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n");
vp->phys[0] = 24;
@@ -965,7 +946,7 @@ static int vortex_probe1(struct device *dev)
vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);
if (vp->full_duplex) {
/* Only advertise the FD media types. */
- vp->advertising &= 0x015F;
+ vp->advertising &= ~0x02A0;
mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);
}
}
@@ -979,30 +960,24 @@ static int vortex_probe1(struct device *dev)
}
/* We do a request_region() to register /proc/ioports info. */
- request_region(ioaddr, VORTEX_TOTAL_SIZE, vp->product_name);
+ request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
/* The 3c59x-specific entries in the device structure. */
dev->open = &vortex_open;
dev->hard_start_xmit = &vortex_start_xmit;
dev->stop = &vortex_close;
dev->get_stats = &vortex_get_stats;
-#ifdef HAVE_PRIVATE_IOCTL
dev->do_ioctl = &vortex_ioctl;
-#endif
-#ifdef NEW_MULTICAST
dev->set_multicast_list = &set_rx_mode;
-#else
- dev->set_multicast_list = &set_multicast_list;
-#endif
- return 0;
+ return dev;
}
static int
vortex_open(struct device *dev)
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
union wn3_config config;
int i;
@@ -1017,28 +992,31 @@ vortex_open(struct device *dev)
dev->name, vp->media_override,
media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
+ } else if (vp->autoselect && pci_tbl[vp->chip_id].drv_flags & HAS_NWAY) {
+ dev->if_port = XCVR_NWAY;
} else if (vp->autoselect) {
/* Find first available media type, starting with 100baseTx. */
dev->if_port = XCVR_100baseTx;
while (! (vp->available_media & media_tbl[dev->if_port].mask))
dev->if_port = media_tbl[dev->if_port].next;
-
- if (vortex_debug > 1)
- printk(KERN_DEBUG "%s: Initial media type %s.\n",
- dev->name, media_tbl[dev->if_port].name);
-
- init_timer(&vp->timer);
- vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
- vp->timer.data = (unsigned long)dev;
- vp->timer.function = &vortex_timer; /* timer handler */
- add_timer(&vp->timer);
} else
dev->if_port = vp->default_media;
+ init_timer(&vp->timer);
+ vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+ vp->timer.data = (unsigned long)dev;
+ vp->timer.function = &vortex_timer; /* timer handler */
+ add_timer(&vp->timer);
+
+ if (vortex_debug > 1)
+ printk(KERN_DEBUG "%s: Initial media type %s.\n",
+ dev->name, media_tbl[dev->if_port].name);
+
+ vp->full_duplex = vp->force_fd;
config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
- if (dev->if_port == XCVR_MII) {
+ if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int mii_reg1, mii_reg5;
EL3WINDOW(4);
/* Read BMSR (reg1) only to clear old status. */
@@ -1078,20 +1056,10 @@ vortex_open(struct device *dev)
outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-#ifdef SA_SHIRQ
/* Use the now-standard shared IRQ implementation. */
if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
return -EAGAIN;
}
-#else
- if (dev->irq == 0 || irq2dev_map[dev->irq] != NULL)
- return -EAGAIN;
- irq2dev_map[dev->irq] = dev;
- if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) {
- irq2dev_map[dev->irq] = NULL;
- return -EAGAIN;
- }
-#endif
if (vortex_debug > 1) {
EL3WINDOW(4);
@@ -1109,9 +1077,11 @@ vortex_open(struct device *dev)
if (dev->if_port == XCVR_10base2)
/* Start the thinnet transceiver. We should really wait 50ms...*/
outw(StartCoax, ioaddr + EL3_CMD);
- EL3WINDOW(4);
- outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
- media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+ if (dev->if_port != XCVR_NWAY) {
+ EL3WINDOW(4);
+ outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+ media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+ }
/* Switch to the stats window, and clear all stats by reading. */
outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1138,22 +1108,23 @@ vortex_open(struct device *dev)
printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name);
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb;
- vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]);
+ vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
vp->rx_ring[i].status = 0; /* Clear complete bit. */
- vp->rx_ring[i].length = PKT_BUF_SZ | LAST_FRAG;
- skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+ vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
+ skb = dev_alloc_skb(PKT_BUF_SZ);
vp->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[i].addr = virt_to_bus(skb->tail);
+ vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
#else
vp->rx_ring[i].addr = virt_to_bus(skb->data);
#endif
}
- vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
+ /* Wrap the ring. */
+ vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
}
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
@@ -1181,14 +1152,16 @@ vortex_open(struct device *dev)
(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
(vp->full_bus_master_rx ? UpComplete : RxComplete) |
(vp->bus_master ? DMADone : 0);
+ vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete |
+ StatsFull | HostError | TxComplete | IntReq
+ | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
outw(vp->status_enable, ioaddr + EL3_CMD);
/* Ack all pending events, and set active indicator mask. */
outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
ioaddr + EL3_CMD);
- outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
- | HostError | TxComplete
- | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
- ioaddr + EL3_CMD);
+ outw(vp->intr_enable, ioaddr + EL3_CMD);
+ if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
+ writel(0x8000, vp->cb_fn_base + 4);
MOD_INC_USE_COUNT;
@@ -1197,24 +1170,23 @@ vortex_open(struct device *dev)
static void vortex_timer(unsigned long data)
{
-#ifdef AUTOMEDIA
struct device *dev = (struct device *)data;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
- unsigned long flags;
+ long ioaddr = dev->base_addr;
+ int next_tick = 0;
int ok = 0;
+ int media_status, mii_status, old_window;
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
dev->name, media_tbl[dev->if_port].name);
- save_flags(flags); cli(); {
- int old_window = inw(ioaddr + EL3_CMD) >> 13;
- int media_status;
- EL3WINDOW(4);
- media_status = inw(ioaddr + Wn4_Media);
- switch (dev->if_port) {
- case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
+ disable_irq(dev->irq);
+ old_window = inw(ioaddr + EL3_CMD) >> 13;
+ EL3WINDOW(4);
+ media_status = inw(ioaddr + Wn4_Media);
+ switch (dev->if_port) {
+ case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) {
ok = 1;
if (vortex_debug > 1)
@@ -1223,27 +1195,40 @@ static void vortex_timer(unsigned long data)
} else if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
-
break;
- case XCVR_MII:
- {
- int mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
+ case XCVR_MII: case XCVR_NWAY:
+ mii_status = mdio_read(ioaddr, vp->phys[0], 1);
+ ok = 1;
+ if (debug > 1)
+ printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
+ dev->name, mii_status);
+ if (mii_status & 0x0004) {
int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
- if (vortex_debug > 1)
- printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "
- "link partner capability %4.4x.\n",
- dev->name, vp->phys[0], mii_reg1, mii_reg5);
- if (mii_reg1 & 0x0004)
- ok = 1;
- break;
+ if (! vp->force_fd && mii_reg5 != 0xffff) {
+ int duplex = (mii_reg5&0x0100) ||
+ (mii_reg5 & 0x01C0) == 0x0040;
+ if (vp->full_duplex != duplex) {
+ vp->full_duplex = duplex;
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII "
+ "#%d link partner capability of %4.4x.\n",
+ dev->name, vp->full_duplex ? "full" : "half",
+ vp->phys[0], mii_reg5);
+ /* Set the full-duplex bit. */
+ outb((vp->full_duplex ? 0x20 : 0) |
+ (dev->mtu > 1500 ? 0x40 : 0),
+ ioaddr + Wn3_MAC_Ctrl);
+ }
+ next_tick = 60*HZ;
+ }
}
+ break;
default: /* Other media types handled by Tx timeouts. */
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
ok = 1;
- }
- if ( ! ok) {
+ }
+ if ( ! ok) {
union wn3_config config;
do {
@@ -1260,8 +1245,7 @@ static void vortex_timer(unsigned long data)
printk(KERN_DEBUG "%s: Media selection failed, now trying "
"%s port.\n",
dev->name, media_tbl[dev->if_port].name);
- vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
- add_timer(&vp->timer);
+ next_tick = media_tbl[dev->if_port].wait;
}
outw((media_status & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
@@ -1273,21 +1257,25 @@ static void vortex_timer(unsigned long data)
outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
- }
- EL3WINDOW(old_window);
- } restore_flags(flags);
- if (vortex_debug > 1)
+ }
+ EL3WINDOW(old_window);
+ enable_irq(dev->irq);
+
+ if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name);
-#endif /* AUTOMEDIA*/
+ if (next_tick) {
+ vp->timer.expires = RUN_AT(next_tick);
+ add_timer(&vp->timer);
+ }
return;
}
static void vortex_tx_timeout(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int j;
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
@@ -1301,7 +1289,7 @@ static void vortex_tx_timeout(struct device *dev)
printk(KERN_ERR "%s: Interrupt posted but not delivered --"
" IRQ blocked by another device?\n", dev->name);
/* Bad idea here.. but we might as well handle a few events. */
- vortex_interrupt IRQ(dev->irq, dev, 0);
+ vortex_interrupt(dev->irq, dev, 0);
}
outw(TxReset, ioaddr + EL3_CMD);
for (j = 200; j >= 0 ; j--)
@@ -1320,8 +1308,8 @@ static void vortex_tx_timeout(struct device *dev)
for (i = 0; i < TX_RING_SIZE; i++) {
printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i,
&vp->tx_ring[i],
- vp->tx_ring[i].length,
- vp->tx_ring[i].status);
+ le32_to_cpu(vp->tx_ring[i].length),
+ le32_to_cpu(vp->tx_ring[i].status));
}
}
#endif
@@ -1351,14 +1339,14 @@ static void vortex_tx_timeout(struct device *dev)
}
/*
- * Handle uncommon interrupt sources. This is a seperate routine to minimize
+ * Handle uncommon interrupt sources. This is a separate routine to minimize
* the cache impact.
*/
static void
vortex_error(struct device *dev, int status)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int do_tx_reset = 0;
int i;
@@ -1398,8 +1386,10 @@ vortex_error(struct device *dev, int status)
DoneDidThat++;
}
}
- if (status & IntReq) /* Restore all interrupt sources. */
- outw(ioaddr + EL3_CMD, vp->status_enable);
+ if (status & IntReq) { /* Restore all interrupt sources. */
+ outw(vp->status_enable, ioaddr + EL3_CMD);
+ outw(vp->intr_enable, ioaddr + EL3_CMD);
+ }
if (status & HostError) {
u16 fifo_diag;
EL3WINDOW(4);
@@ -1445,7 +1435,7 @@ static int
vortex_start_xmit(struct sk_buff *skb, struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
if (jiffies - dev->trans_start >= TX_TIMEOUT)
@@ -1455,7 +1445,6 @@ vortex_start_xmit(struct sk_buff *skb, struct device *dev)
/* Put out the doubleword header... */
outl(skb->len, ioaddr + TX_FIFO);
-#ifdef VORTEX_BUS_MASTER
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
@@ -1473,16 +1462,6 @@ vortex_start_xmit(struct sk_buff *skb, struct device *dev)
/* Interrupt us when the FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
-#else
- /* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
- DEV_FREE_SKB(skb);
- if (inw(ioaddr + TxFree) > 1536) {
- clear_bit(0, (void*)&dev->tbusy);
- } else
- /* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-#endif /* bus master */
dev->trans_start = jiffies;
@@ -1510,6 +1489,7 @@ vortex_start_xmit(struct sk_buff *skb, struct device *dev)
outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */
}
}
+ vp->stats.tx_bytes += skb->len;
return 0;
}
@@ -1517,7 +1497,7 @@ static int
boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
if (jiffies - dev->trans_start >= TX_TIMEOUT)
@@ -1539,13 +1519,12 @@ boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
dev->name);
return 1;
- }
- /* end change 06/25/97 M. Sievers */
+ }
vp->tx_skbuff[entry] = skb;
vp->tx_ring[entry].next = 0;
- vp->tx_ring[entry].addr = virt_to_bus(skb->data);
- vp->tx_ring[entry].length = skb->len | LAST_FRAG;
- vp->tx_ring[entry].status = skb->len | TxIntrUploaded;
+ vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+ vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
+ vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
save_flags(flags);
cli();
@@ -1554,7 +1533,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
for (i = 600; i >= 0 ; i--)
if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
break;
- prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
+ prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
if (inl(ioaddr + DownListPtr) == 0) {
outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
queued_packet++;
@@ -1566,38 +1545,44 @@ boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
vp->tx_full = 1;
else { /* Clear previous interrupt enable. */
- prev_entry->status &= ~TxIntrUploaded;
+ prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
clear_bit(0, (void*)&dev->tbusy);
}
dev->trans_start = jiffies;
+ vp->stats.tx_bytes += skb->len;
return 0;
}
}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef SA_SHIRQ /* Use the now-standard shared IRQ implementation. */
struct device *dev = dev_id;
-#else
- struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
- struct vortex_private *vp;
- int ioaddr, status;
- int latency;
+ struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ long ioaddr;
+ int latency, status;
int work_done = max_interrupt_work;
- vp = (struct vortex_private *)dev->priv;
- if (test_and_set_bit(0, (void*)&vp->in_interrupt)) {
+#if defined(__i386__)
+ /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+ if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+ printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+ dev->name);
+ dev->interrupt = 0; /* Avoid halting machine. */
+ return;
+ }
+#else
+ if (dev->interrupt) {
printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
return;
}
+ dev->interrupt = 1;
+#endif
dev->interrupt = 1;
ioaddr = dev->base_addr;
latency = inb(ioaddr + Timer);
-
status = inw(ioaddr + EL3_STATUS);
if (vortex_debug > 4)
@@ -1646,17 +1631,23 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
mark_bh(NET_BH);
}
}
-#ifdef VORTEX_BUS_MASTER
if (status & DMADone) {
- outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
- clear_bit(0, (void*)&dev->tbusy);
- DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
- mark_bh(NET_BH);
+ if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
+ outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+ DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+ if (inw(ioaddr + TxFree) > 1536) {
+ clear_bit(0, (void*)&dev->tbusy);
+ mark_bh(NET_BH);
+ } else /* Interrupt when FIFO has room for max-sized packet. */
+ outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ }
}
-#endif
/* Check for all uncommon interrupts at once. */
- if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
+ if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
+ if (status == 0xffff)
+ break;
vortex_error(dev, status);
+ }
if (--work_done < 0) {
if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
@@ -1669,13 +1660,14 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
/* Disable all pending interrupts. */
outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
- /* Set a timer to reenable interrupts. */
-
+ /* The timer will reenable interrupts. */
break;
}
}
/* Acknowledge the IRQ. */
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+ if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
+ writel(0x8000, vp->cb_fn_base + 4);
} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
@@ -1683,16 +1675,18 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
dev->name, status);
+#if defined(__i386__)
+ clear_bit(0, (void*)&dev->interrupt);
+#else
dev->interrupt = 0;
- clear_bit(0, (void*)&vp->in_interrupt);
+#endif
return;
}
-static int
-vortex_rx(struct device *dev)
+static int vortex_rx(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int i;
short rx_status;
@@ -1715,28 +1709,32 @@ vortex_rx(struct device *dev)
int pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
- skb = DEV_ALLOC_SKB(pkt_len + 5);
+ skb = dev_alloc_skb(pkt_len + 5);
if (vortex_debug > 4)
printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
if (skb != NULL) {
skb->dev = dev;
-#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
- insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
- (pkt_len + 3) >> 2);
+ if (vp->bus_master &&
+ ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+ outl(virt_to_bus(skb_put(skb, pkt_len)),
+ ioaddr + Wn7_MasterAddr);
+ outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+ outw(StartDMAUp, ioaddr + EL3_CMD);
+ while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
+ ;
+ } else {
+ insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
+ (pkt_len + 3) >> 2);
+ }
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
-#else
- skb->len = pkt_len;
- /* 'skb->data' points to the start of sk_buff data area. */
- insl(ioaddr + RX_FIFO, skb->data, (pkt_len + 3) >> 2);
- outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
-#endif /* KERNEL_1_3_0 */
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
+ vp->stats.rx_bytes += skb->len;
/* Wait a limited time to go to next packet. */
for (i = 200; i >= 0; i--)
if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
@@ -1762,7 +1760,7 @@ boomerang_rx(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
int entry = vp->cur_rx % RX_RING_SIZE;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int rx_status;
int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
@@ -1770,8 +1768,9 @@ boomerang_rx(struct device *dev)
printk(KERN_DEBUG " In boomerang_rx(), status %4.4x, rx_status "
"%4.4x.\n",
inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
- while ((--rx_work_limit >= 0) &&
- ((rx_status = vp->rx_ring[entry].status) & RxDComplete)) {
+ while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
+ if (--rx_work_limit < 0)
+ break;
if (rx_status & RxDError) { /* Error, update stats. */
unsigned char rx_error = rx_status >> 16;
if (vortex_debug > 2)
@@ -1787,6 +1786,7 @@ boomerang_rx(struct device *dev)
int pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
+ vp->stats.rx_bytes += pkt_len;
if (vortex_debug > 4)
printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
@@ -1794,41 +1794,28 @@ boomerang_rx(struct device *dev)
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
if (pkt_len < rx_copybreak
- && (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) {
+ && (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
skb->dev = dev;
-#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
memcpy(skb_put(skb, pkt_len),
- bus_to_virt(vp->rx_ring[entry].addr),
+ bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
pkt_len);
-#else
- memcpy(skb->data, bus_to_virt(vp->rx_ring[entry].addr), pkt_len);
- skb->len = pkt_len;
-#endif
rx_copy++;
- } else{
+ } else {
void *temp;
/* Pass up the skbuff already on the Rx ring. */
skb = vp->rx_skbuff[entry];
- if (skb == NULL) {
- printk(KERN_WARNING "%s: in boomerang_rx -- attempt to use NULL skb caught\n", dev->name);
- break;
- }
vp->rx_skbuff[entry] = NULL;
-#if LINUX_VERSION_CODE >= 0x10300
temp = skb_put(skb, pkt_len);
-#else
- temp = skb->data;
-#endif
/* Remove this checking code for final release. */
- if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
+ if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp)
printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
" in boomerang_rx: %p vs. %p.\n", dev->name,
- bus_to_virt(vp->rx_ring[entry].addr), temp);
+ bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+ temp);
rx_nocopy++;
}
-#if LINUX_VERSION_CODE > 0x10300
skb->protocol = eth_type_trans(skb, dev);
{ /* Use hardware checksum info. */
int csum_bits = rx_status & 0xee000000;
@@ -1839,9 +1826,6 @@ boomerang_rx(struct device *dev)
rx_csumhits++;
}
}
-#else
- skb->len = pkt_len;
-#endif
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
@@ -1853,29 +1837,17 @@ boomerang_rx(struct device *dev)
struct sk_buff *skb;
entry = vp->dirty_rx % RX_RING_SIZE;
if (vp->rx_skbuff[entry] == NULL) {
- skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
- if (skb == NULL) {
- printk(KERN_DEBUG "%s: in boomerang_rx -- could not allocate skbuff\n", dev->name);
+ skb = dev_alloc_skb(PKT_BUF_SZ);
+ if (skb == NULL)
break; /* Bad news! */
- }
skb->dev = dev; /* Mark as being used by this device. */
-#if LINUX_VERSION_CODE > 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
-#else
- vp->rx_ring[entry].addr = virt_to_bus(skb->data);
-#endif
+ vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
outw(UpUnstall, ioaddr + EL3_CMD);
}
-
- if (vp->dirty_rx >= RX_RING_SIZE ) {
- vp->cur_rx -= RX_RING_SIZE;
- vp->dirty_rx -= RX_RING_SIZE;
- }
-
return 0;
}
@@ -1883,7 +1855,7 @@ static int
vortex_close(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int i;
dev->start = 0;
@@ -1910,12 +1882,7 @@ vortex_close(struct device *dev)
/* Turn off thinnet power. Green! */
outw(StopCoax, ioaddr + EL3_CMD);
-#ifdef SA_SHIRQ
free_irq(dev->irq, dev);
-#else
- free_irq(dev->irq);
- irq2dev_map[dev->irq] = 0;
-#endif
outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
@@ -1945,8 +1912,7 @@ vortex_close(struct device *dev)
return 0;
}
-static struct enet_statistics *
-vortex_get_stats(struct device *dev)
+static struct net_device_stats *vortex_get_stats(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
unsigned long flags;
@@ -1967,7 +1933,7 @@ vortex_get_stats(struct device *dev)
table. This is done by checking that the ASM (!) code generated uses
atomic updates with '+='.
*/
-static void update_stats(int ioaddr, struct device *dev)
+static void update_stats(long ioaddr, struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
@@ -1998,20 +1964,14 @@ static void update_stats(int ioaddr, struct device *dev)
return;
}
-#ifdef HAVE_PRIVATE_IOCTL
static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
u16 *data = (u16 *)&rq->ifr_data;
int phy = vp->phys[0] & 0x1f;
- if (vortex_debug > 2)
- printk(KERN_DEBUG "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
- dev->name, rq->ifr_ifrn.ifrn_name, cmd,
- data[0], data[1], data[2], data[3]);
-
- switch(cmd) {
+ switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = phy;
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
@@ -2021,22 +1981,20 @@ static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!suser())
return -EPERM;
+ EL3WINDOW(4);
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
default:
return -EOPNOTSUPP;
}
}
-#endif /* HAVE_PRIVATE_IOCTL */
-/* This new version of set_rx_mode() supports v1.4 kernels.
- The Vortex chip has no documented multicast filter, so the only
+/* Pre-Cyclone chips have no documented multicast filter, so the only
multicast setting is to receive all multicast frames. At least
the chip has a very clean way to set the mode, unlike many others. */
-static void
-set_rx_mode(struct device *dev)
+static void set_rx_mode(struct device *dev)
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int new_mode;
if (dev->flags & IFF_PROMISC) {
@@ -2050,14 +2008,6 @@ set_rx_mode(struct device *dev)
outw(new_mode, ioaddr + EL3_CMD);
}
-#ifndef NEW_MULTICAST
-/* The old interface to set the Rx mode. */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
-{
- set_rx_mode(dev);
-}
-#endif
/* MII transceiver control section.
@@ -2068,7 +2018,7 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back PCI I/O cycles, but we insert a delay to avoid
"overclocking" issues. */
-#define mdio_delay() udelay(1)
+#define mdio_delay() inl(mdio_addr)
#define MDIO_SHIFT_CLK 0x01
#define MDIO_DIR_WRITE 0x04
@@ -2079,11 +2029,11 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
/* Generate the preamble required for initial synchronization and
a few older transceivers. */
-static void mdio_sync(int ioaddr, int bits)
+static void mdio_sync(long ioaddr, int bits)
{
- int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
- /* Establish sync by sending at least 32 logic ones. */
+ /* Establish sync by sending at least 32 logic ones. */
while (-- bits >= 0) {
outw(MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
@@ -2092,12 +2042,12 @@ static void mdio_sync(int ioaddr, int bits)
}
}
-static int mdio_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
{
int i;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned int retval = 0;
- int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
if (mii_preamble_required)
mdio_sync(ioaddr, 32);
@@ -2118,13 +2068,17 @@ static int mdio_read(int ioaddr, int phy_id, int location)
outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
- return retval>>1 & 0xffff;
+#if 0
+ return (retval>>1) & 0x1ffff;
+#else
+ return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
+#endif
}
-static void mdio_write(int ioaddr, int phy_id, int location, int value)
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
{
int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
- int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
int i;
if (mii_preamble_required)
@@ -2151,8 +2105,7 @@ static void mdio_write(int ioaddr, int phy_id, int location, int value)
#ifdef MODULE
-void
-cleanup_module(void)
+void cleanup_module(void)
{
struct device *next_dev;
@@ -2162,11 +2115,14 @@ cleanup_module(void)
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_vortex_dev) {
- next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
+ struct vortex_private *vp=(void *)(root_vortex_dev->priv);
+ next_dev = vp->next_module;
unregister_netdev(root_vortex_dev);
outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
- release_region(root_vortex_dev->base_addr, VORTEX_TOTAL_SIZE);
+ release_region(root_vortex_dev->base_addr,
+ pci_tbl[vp->chip_id].io_size);
kfree(root_vortex_dev);
+ kfree(vp->priv_addr);
root_vortex_dev = next_dev;
}
}
@@ -2177,7 +2133,7 @@ cleanup_module(void)
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
- * compile-command-alt1: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c59x_cb.o"
+ * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index 6a9c0990c..cd3ab6bd6 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -67,7 +67,7 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
#endif
/*
- * Define various macros for Channel Attention, word swapping etc., dependant
+ * Define various macros for Channel Attention, word swapping etc., dependent
* on architecture. MVME and BVME are 680x0 based, otherwise it is Intel.
*/
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index cd638f3df..064edb07f 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -37,7 +37,7 @@
68K Macintosh. Support >16bit I/O spaces
Paul Gortmaker : add kmod support for auto-loading of the 8390
module by all drivers that require it.
-
+ Alan Cox : Spinlocking work, added 'BUG_83C690'
Sources:
The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -72,6 +72,8 @@ static const char *version =
#define NS8390_CORE
#include "8390.h"
+#define BUG_83C690
+
/* These are the operational function interfaces to board-specific
routines.
void reset_8390(struct device *dev)
@@ -110,6 +112,34 @@ static void ei_rx_overrun(struct device *dev);
static void NS8390_trigger_send(struct device *dev, unsigned int length,
int start_page);
static void set_multicast_list(struct device *dev);
+static void do_set_multicast_list(struct device *dev);
+
+/*
+ * SMP and the 8390 setup.
+ *
+ * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
+ * a page register that controls bank and packet buffer access. We guard
+ * this with ei_local->page_lock. Nobody should assume or set the page other
+ * than zero when the lock is not held. Lock holders must restore page 0
+ * before unlocking. Even pure readers must take the lock to protect in
+ * page 0.
+ *
+ * To make life difficult the chip can also be very slow. We therefore can't
+ * just use spinlocks. For the longer lockups we disable the irq the device
+ * sits on and hold the lock. We must hold the lock because there is a dual
+ * processor case other than interrupts (get stats/set multicast list in
+ * parallel with each other and transmit).
+ *
+ * Note: in theory we can just disable the irq on the card _but_ there is
+ * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ * enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ * Finally by special arrangement for the purpose of being generally
+ * annoying the transmit function is called bh atomic. That places
+ * restrictions on the user context callers as disable_irq won't save
+ * them.
+ */
+
/* Open/initialize the board. This routine goes all-out, setting everything
@@ -118,6 +148,7 @@ static void set_multicast_list(struct device *dev);
*/
int ei_open(struct device *dev)
{
+ unsigned long flags;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
/* This can't happen unless somebody forgot to call ethdev_init(). */
@@ -127,7 +158,14 @@ int ei_open(struct device *dev)
return -ENXIO;
}
+ /*
+ * Grab the page lock so we own the register set, then call
+ * the init function.
+ */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
NS8390_init(dev, 1);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
dev->start = 1;
ei_local->irqlock = 0;
return 0;
@@ -136,7 +174,16 @@ int ei_open(struct device *dev)
/* Opposite of above. Only used when "ifconfig <devname> down" is done. */
int ei_close(struct device *dev)
{
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ unsigned long flags;
+
+ /*
+ * Hold the page lock during close
+ */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
NS8390_init(dev, 0);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
dev->start = 0;
return 0;
}
@@ -146,24 +193,39 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
int e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int length, send_length, output_page;
+ unsigned long flags;
/*
* We normally shouldn't be called if dev->tbusy is set, but the
* existing code does anyway. If it has been too long since the
- * last Tx, we assume the board has died and kick it.
+ * last Tx, we assume the board has died and kick it. We are
+ * bh_atomic here.
*/
if (dev->tbusy)
{ /* Do timeouts, just like the 8003 driver. */
- int txsr = inb(e8390_base+EN0_TSR), isr;
+ int txsr;
+ int isr;
int tickssofar = jiffies - dev->trans_start;
+
+ /*
+ * Need the page lock. Now see what went wrong. This bit is
+ * fast.
+ */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ txsr = inb(e8390_base+EN0_TSR);
if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX)))
+ {
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
return 1;
+ }
ei_local->stat.tx_errors++;
isr = inb(e8390_base+EN0_ISR);
if (dev->start == 0)
{
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
return 1;
}
@@ -184,22 +246,54 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
ei_local->interface_num ^= 1; /* Try a different xcvr. */
}
+ /*
+ * Play shuffle the locks, a reset on some chips takes a few
+ * mS. We very rarely hit this point.
+ */
+
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+ /* Ugly but a reset can be slow, yet must be protected */
+
+ disable_irq(dev->irq);
+ synchronize_irq();
+ spin_lock(&ei_local->page_lock);
+
/* Try to restart the card. Perhaps the user has fixed something. */
ei_reset_8390(dev);
NS8390_init(dev, 1);
+
+ spin_unlock(&ei_local->page_lock);
+ enable_irq(dev->irq);
dev->trans_start = jiffies;
}
length = skb->len;
- /* Mask interrupts from the ethercard. */
+ /* Mask interrupts from the ethercard.
+ SMP: We have to grab the lock here otherwise the IRQ handler
+ on another CPU can flip window and race the IRQ mask set. We end
+ up trashing the mcast filter not disabling irqs if we dont lock */
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
outb_p(0x00, e8390_base + EN0_IMR);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+
+ /*
+ * Slow phase with lock held.
+ */
+
disable_irq(dev->irq);
synchronize_irq();
+
+ spin_lock(&ei_local->page_lock);
+
if (dev->interrupt)
{
printk(KERN_WARNING "%s: Tx request while isr active.\n",dev->name);
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
ei_local->stat.tx_errors++;
dev_kfree_skb(skb);
@@ -243,6 +337,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
ei_local->irqlock = 0;
dev->tbusy = 1;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+ spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
ei_local->stat.tx_errors++;
return 1;
@@ -294,6 +389,8 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
/* Turn 8390 interrupts back on. */
ei_local->irqlock = 0;
outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+ spin_unlock(&ei_local->page_lock);
enable_irq(dev->irq);
dev_kfree_skb (skb);
@@ -320,6 +417,13 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
e8390_base = dev->base_addr;
ei_local = (struct ei_device *) dev->priv;
+
+ /*
+ * Protect the irq test too.
+ */
+
+ spin_lock(&ei_local->page_lock);
+
if (dev->interrupt || ei_local->irqlock)
{
#if 1 /* This might just be an interrupt for a PCI device sharing this line */
@@ -330,15 +434,17 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dev->name, inb_p(e8390_base + EN0_ISR),
inb_p(e8390_base + EN0_IMR));
#endif
+ spin_unlock(&ei_local->page_lock);
return;
}
+
dev->interrupt = 1;
/* Change to page 0 and read the intr status reg. */
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
if (ei_debug > 3)
- printk("%s: interrupt(isr=%#2.2x).\n", dev->name,
+ printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
inb_p(e8390_base + EN0_ISR));
/* !!Assumption!! -- we stay in page 0. Don't break this. */
@@ -386,15 +492,16 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
if (nr_serviced >= MAX_SERVICE)
{
- printk("%s: Too much work at interrupt, status %#2.2x\n",
+ printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
dev->name, interrupts);
outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
} else {
- printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
+ printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
}
}
dev->interrupt = 0;
+ spin_unlock(&ei_local->page_lock);
return;
}
@@ -405,6 +512,8 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
* letting the failed packet sit and collect dust in the Tx buffer. This
* is a much better solution as it avoids kernel based Tx timeouts, and
* an unnecessary card reset.
+ *
+ * Called with lock held
*/
static void ei_tx_err(struct device *dev)
@@ -443,7 +552,7 @@ static void ei_tx_err(struct device *dev)
}
/* We have finished a transmit: check for errors and then trigger the next
- packet to be sent. */
+ packet to be sent. Called with lock held */
static void ei_tx_intr(struct device *dev)
{
@@ -532,7 +641,8 @@ static void ei_tx_intr(struct device *dev)
mark_bh (NET_BH);
}
-/* We have a good packet(s), get it/them out of the buffers. */
+/* We have a good packet(s), get it/them out of the buffers.
+ Called with lock held */
static void ei_receive(struct device *dev)
{
@@ -659,6 +769,8 @@ static void ei_receive(struct device *dev)
* the updated datasheets, or "the NIC may act in an unpredictable manner."
* This includes causing "the NIC to defer indefinitely when it is stopped
* on a busy network." Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10mS or so.
*/
static void ei_rx_overrun(struct device *dev)
@@ -726,19 +838,26 @@ static void ei_rx_overrun(struct device *dev)
outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
}
+/*
+ * Collect the stats. This is called unlocked and from several contexts.
+ */
+
static struct net_device_stats *get_stats(struct device *dev)
{
int ioaddr = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ unsigned long flags;
/* If the card is stopped, just return the present stats. */
if (dev->start == 0)
return &ei_local->stat;
+ spin_lock_irqsave(&ei_local->page_lock,flags);
/* Read the counter registers, assuming we are in page 0. */
ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1);
ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
return &ei_local->stat;
}
@@ -794,14 +913,14 @@ static inline void make_mc_bits(u8 *bits, struct device *dev)
}
/*
- * Set or clear the multicast filter for this adaptor.
+ * Set or clear the multicast filter for this adaptor. May be called
+ * from a BH in 2.1.x. Must be called with lock held.
*/
-static void set_multicast_list(struct device *dev)
+static void do_set_multicast_list(struct device *dev)
{
int e8390_base = dev->base_addr;
int i;
- unsigned long flags;
struct ei_device *ei_local = (struct ei_device*)dev->priv;
if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
@@ -825,21 +944,19 @@ static void set_multicast_list(struct device *dev)
* them as r/w so this is a bug. The SMC 83C790 (SMC Ultra and
* Ultra32 EISA) appears to have this bug fixed.
*/
+
if (dev->start)
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
- save_flags(flags);
- cli();
outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
for(i = 0; i < 8; i++)
{
outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
-#ifdef NOT_83C690
+#ifndef BUG_83C690
if(inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
#endif
}
outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
- restore_flags(flags);
if(dev->flags&IFF_PROMISC)
outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
@@ -847,12 +964,29 @@ static void set_multicast_list(struct device *dev)
outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
else
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
-}
+ }
+
+/*
+ * Called without lock held. This is invoked from user context and may
+ * be parallel to just about everything else. Its also fairly quick and
+ * not called too often. Must protect against both bh and irq users
+ */
+
+static void set_multicast_list(struct device *dev)
+{
+ unsigned long flags;
+ struct ei_device *ei_local = (struct ei_device*)dev->priv;
+
+ spin_lock_irqsave(&ei_local->page_lock, flags);
+ do_set_multicast_list(dev);
+ spin_unlock_irqrestore(&ei_local->page_lock, flags);
+}
/*
* Initialize the rest of the 8390 device structure. Do NOT __initfunc
* this, as it is used by 8390 based modular drivers too.
*/
+
int ethdev_init(struct device *dev)
{
if (ei_debug > 1)
@@ -867,6 +1001,7 @@ int ethdev_init(struct device *dev)
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct ei_device));
ei_local = (struct ei_device *)dev->priv;
+ spin_lock_init(&ei_local->page_lock);
}
dev->hard_start_xmit = &ei_start_xmit;
@@ -883,13 +1018,16 @@ int ethdev_init(struct device *dev)
/* This page of functions should be 8390 generic */
/* Follow National Semi's recommendations for initializing the "NIC". */
+/*
+ * Must be called with lock held.
+ */
+
void NS8390_init(struct device *dev, int startp)
{
int e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) dev->priv;
int i;
int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
- unsigned long flags;
if(sizeof(struct e8390_pkt_hdr)!=4)
panic("8390.c: header struct mispacked\n");
@@ -914,8 +1052,7 @@ void NS8390_init(struct device *dev, int startp)
outb_p(0x00, e8390_base + EN0_IMR);
/* Copy the station address into the DS8390 registers. */
- save_flags(flags);
- cli();
+
outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
for(i = 0; i < 6; i++)
{
@@ -926,7 +1063,7 @@ void NS8390_init(struct device *dev, int startp)
outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
- restore_flags(flags);
+
dev->tbusy = 0;
dev->interrupt = 0;
ei_local->tx1 = ei_local->tx2 = 0;
@@ -940,18 +1077,20 @@ void NS8390_init(struct device *dev, int startp)
outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
/* 3c503 TechMan says rxconfig only after the NIC is started. */
outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */
- set_multicast_list(dev); /* (re)load the mcast table */
+ do_set_multicast_list(dev); /* (re)load the mcast table */
}
return;
}
-/* Trigger a transmit start, assuming the length is valid. */
+/* Trigger a transmit start, assuming the length is valid.
+ Always called with the page lock held */
+
static void NS8390_trigger_send(struct device *dev, unsigned int length,
int start_page)
{
int e8390_base = dev->base_addr;
- struct ei_device *ei_local = (struct ei_device *) dev->priv;
-
+ struct ei_device *ei_local = (struct ei_device *) dev->priv;
+
outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
if (inb_p(e8390_base) & E8390_TRANS)
@@ -968,6 +1107,12 @@ static void NS8390_trigger_send(struct device *dev, unsigned int length,
#ifdef MODULE
+EXPORT_SYMBOL(ei_open);
+EXPORT_SYMBOL(ei_close);
+EXPORT_SYMBOL(ei_interrupt);
+EXPORT_SYMBOL(ethdev_init);
+EXPORT_SYMBOL(NS8390_init);
+
struct module *NS8390_module = NULL;
int init_module(void)
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 52d4e9c9b..4f280b013 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -155,30 +155,30 @@ extern void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
things in there should be here!) */
/* You have one of these per-board */
struct ei_device {
- const char *name;
- void (*reset_8390)(struct device *);
- void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
- void (*block_output)(struct device *, int, const unsigned char *, int);
- void (*block_input)(struct device *, int, struct sk_buff *, int);
- unsigned char mcfilter[8];
- unsigned open:1;
- unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
- unsigned txing:1; /* Transmit Active */
- unsigned irqlock:1; /* 8390's intrs disabled when '1'. */
- unsigned dmaing:1; /* Remote DMA Active */
- unsigned char tx_start_page, rx_start_page, stop_page;
- unsigned char current_page; /* Read pointer in buffer */
- unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
- unsigned char txqueue; /* Tx Packet buffer queue length. */
- short tx1, tx2; /* Packet lengths for ping-pong tx. */
- short lasttx; /* Alpha version consistency check. */
- unsigned char reg0; /* Register '0' in a WD8013 */
- unsigned char reg5; /* Register '5' in a WD8013 */
- unsigned char saved_irq; /* Original dev->irq value. */
- /* The new statistics table. */
- struct net_device_stats stat;
- unsigned char *reg_offset; /* Register mapping table */
- unsigned long priv; /* Private field to store bus IDs etc. */
+ const char *name;
+ void (*reset_8390)(struct device *);
+ void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
+ void (*block_output)(struct device *, int, const unsigned char *, int);
+ void (*block_input)(struct device *, int, struct sk_buff *, int);
+ unsigned char mcfilter[8];
+ unsigned open:1;
+ unsigned word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */
+ unsigned txing:1; /* Transmit Active */
+ unsigned irqlock:1; /* 8390's intrs disabled when '1'. */
+ unsigned dmaing:1; /* Remote DMA Active */
+ unsigned char tx_start_page, rx_start_page, stop_page;
+ unsigned char current_page; /* Read pointer in buffer */
+ unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
+ unsigned char txqueue; /* Tx Packet buffer queue length. */
+ short tx1, tx2; /* Packet lengths for ping-pong tx. */
+ short lasttx; /* Alpha version consistency check. */
+ unsigned char reg0; /* Register '0' in a WD8013 */
+ unsigned char reg5; /* Register '5' in a WD8013 */
+ unsigned char saved_irq; /* Original dev->irq value. */
+ struct net_device_stats stat; /* The new statistics table. */
+ u32 *reg_offset; /* Register mapping table */
+ spinlock_t page_lock; /* Page register locks */
+ unsigned long priv; /* Private field to store bus IDs etc. */
};
/* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -190,12 +190,12 @@ struct ei_device {
#define ei_status (*(struct ei_device *)(dev->priv))
/* Some generic ethernet register configurations. */
-#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
-#define E8390_RX_IRQ_MASK 0x5
-#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */
-#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
-#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
-#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
+#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */
+#define E8390_RX_IRQ_MASK 0x5
+#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */
+#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */
+#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */
+#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
@@ -208,6 +208,10 @@ struct ei_device {
#define E8390_PAGE1 0x40 /* using the two high-order bits */
#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
+/*
+ * Only generate indirect loads given a machine that needs them.
+ */
+
#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE)
#define EI_SHIFT(x) (ei_local->reg_offset[x])
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index df7d7f60c..e0ca210b1 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -59,7 +59,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
tristate '3c515 ISA Fast EtherLink' CONFIG_3C515
tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
fi
- bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
+ tristate 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE
bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC
if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
tristate 'WD80*3 support' CONFIG_WD80x3
@@ -85,17 +85,15 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
fi
bool 'Other ISA cards' CONFIG_NET_ISA
if [ "$CONFIG_NET_ISA" = "y" ]; then
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
- fi
+ tristate 'AT1700/1720 support' CONFIG_AT1700
tristate 'Cabletron E21xx support' CONFIG_E2100
tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
tristate 'EtherExpress 16 support' CONFIG_EEXPRESS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
- tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
fi
+ tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
tristate 'HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100
@@ -228,6 +226,11 @@ fi
#
dep_tristate 'Comtrol Hostess SV-11 support' CONFIG_HOSTESS_SV11 m
#
+# The COSA/SRP driver has not been tested as non-modular yet.
+#
+dep_tristate 'COSA/SRP sync serial boards support' CONFIG_COSA m
+tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
+#
if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
bool 'WAN drivers' CONFIG_WAN_DRIVERS
if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 2dc86b499..572e4ec27 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -5,7 +5,7 @@
SUB_DIRS :=
MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) hamradio
+ALL_SUB_DIRS := $(SUB_DIRS) hamradio irda
L_TARGET := net.a
L_OBJS := auto_irq.o
@@ -384,6 +384,10 @@ endif
ifeq ($(CONFIG_LANCE),y)
L_OBJS += lance.o
+else
+ ifeq ($(CONFIG_LANCE),m)
+ M_OBJS += lance.o
+ endif
endif
ifeq ($(CONFIG_PCNET32),y)
@@ -752,6 +756,16 @@ else
endif
endif
+ifeq ($(CONFIG_COSA),y)
+L_OBJS += cosa.o
+CONFIG_SYNCPPP_BUILTIN = y
+else
+ ifeq ($(CONFIG_COSA),m)
+ CONFIG_SYNCPPP_MODULE = y
+ M_OBJS += cosa.o
+ endif
+endif
+
# If anything built-in uses syncppp, then build it into the kernel also.
# If not, but a module uses it, build as a module.
@@ -812,7 +826,7 @@ ifdef CONFIG_8390_BUILTIN
L_OBJS += 8390.o
else
ifdef CONFIG_8390_MODULE
- M_OBJS += 8390.o
+ MX_OBJS += 8390.o
endif
endif
@@ -965,6 +979,14 @@ else
endif
endif
+ifeq ($(CONFIG_RCPCI),y)
+L_OBJS += rcpci.o
+else
+ ifeq ($(CONFIG_RCPCI),m)
+ M_OBJS += rcpci.o
+ endif
+endif
+
ifeq ($(CONFIG_MACE),y)
L_OBJS += mace.o
endif
@@ -1013,13 +1035,6 @@ endif
#
# HIPPI adapters
#
-ifeq ($(CONFIG_CERN_HIPPI),y)
-L_OBJS += cern_hippi.o
-else
- ifeq ($(CONFIG_CERN_HIPPI),m)
- M_OBJS += cern_hippi.o
- endif
-endif
ifeq ($(CONFIG_ROADRUNNER),y)
L_OBJS += rrunner.o
@@ -1029,6 +1044,14 @@ else
endif
endif
+ifeq ($(CONFIG_IRDA),y)
+SUB_DIRS += irda
+else
+ ifeq ($(CONFIG_IRDA),m)
+ MOD_SUB_DIRS += irda
+ endif
+endif
+
include $(TOPDIR)/Rules.make
clean:
@@ -1036,3 +1059,6 @@ clean:
wanpipe.o: $(WANPIPE_OBJS)
ld -r -o $@ $(WANPIPE_OBJS)
+
+rcpci.o: rcpci45.o rclanmtl.o
+ $(LD) -r -o rcpci.o rcpci45.o rclanmtl.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index a3f8e68a9..eece1bfe3 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -111,6 +111,8 @@ extern int rtl8139_probe(struct device *dev);
extern int hplance_probe(struct device *dev);
extern int via_rhine_probe(struct device *dev);
extern int tc515_probe(struct device *dev);
+extern int lance_probe(struct device *dev);
+extern int rcpci_probe(struct device *);
/* Gigabit Ethernet adapters */
extern int yellowfin_probe(struct device *dev);
@@ -126,7 +128,6 @@ extern int dfx_probe(struct device *dev);
extern int apfddi_init(struct device *dev);
/* HIPPI boards */
-extern int cern_hippi_probe(struct device *);
extern int rr_hippi_probe(struct device *);
struct devprobe
@@ -172,12 +173,12 @@ struct devprobe pci_probes[] __initdata = {
#ifdef CONFIG_DGRS
{dgrs_probe, 0},
#endif
+#ifdef CONFIG_RCPCI
+ {rcpci_probe, 0},
+#endif
#ifdef CONFIG_VORTEX
{tc59x_probe, 0},
#endif
-#ifdef CONFIG_DEC_ELCP
- {tulip_probe, 0},
-#endif
#ifdef CONFIG_NE2K_PCI
{ne2k_pci_probe, 0},
#endif
@@ -187,6 +188,9 @@ struct devprobe pci_probes[] __initdata = {
#ifdef CONFIG_EEXPRESS_PRO100 /* Intel EtherExpress Pro/100 */
{eepro100_probe, 0},
#endif
+#ifdef CONFIG_DEC_ELCP
+ {tulip_probe, 0},
+#endif
#ifdef CONFIG_DE4X5 /* DEC DE425, DE434, DE435 adapters */
{de4x5_probe, 0},
#endif
@@ -300,6 +304,9 @@ struct devprobe isa_probes[] __initdata = {
#ifdef CONFIG_NE2000 /* ISA (use ne2k-pci for PCI cards) */
{ne_probe, 0},
#endif
+#ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */
+ {lance_probe, 0},
+#endif
#ifdef CONFIG_SMC9194
{smc_init, 0},
#endif
@@ -536,9 +543,6 @@ static int hippi_probe(struct device *dev)
return 1;
if (1
-#ifdef CONFIG_CERN_HIPPI
- && cern_hippi_probe(dev)
-#endif
#ifdef CONFIG_ROADRUNNER
&& rr_hippi_probe(dev)
#endif
@@ -713,6 +717,9 @@ trif_probe(struct device *dev)
#ifdef CONFIG_SKTR
&& sktr_probe(dev)
#endif
+#ifdef CONFIG_SMCTR
+ && smctr_probe(dev)
+#endif
&& 1 ) {
return 1; /* -ENODEV or -EAGAIN would be more accurate. */
}
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index c6950ad28..e5e2f572f 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -407,7 +407,6 @@ cleanup_module(void)
release_region(dev->base_addr, AC_IO_EXTENT);
if (ei_status.reg0)
iounmap((void *)dev->mem_start);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 7eef6b801..44709f341 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -7,14 +7,17 @@
* Thanks to Alteon and 3Com for providing hardware and documentation
* enabling me to write this driver.
*
+ * A mailing list for discussing the use of this driver has been
+ * setup, please subscribe to the lists if you have any questions
+ * about the driver. Send mail to linux-acenic-help@sunsite.auc.dk to
+ * see how to subscribe.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the 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 DEBUG 1
-#define RX_DMA_SKBUFF 1
#define PKT_COPY_THRESHOLD 300
#include <linux/module.h>
@@ -59,10 +62,6 @@
* firmware. Also the programming interface is quite neat, except for
* the parts dealing with the i2c eeprom on the card ;-)
*
- * A number of standard Ethernet receive skb's are now allocated at
- * init time and not released before the driver is unloaded. This
- * makes it possible to do ifconfig down/up.
- *
* Using jumbo frames:
*
* To enable jumbo frames, simply specify an mtu between 1500 and 9000
@@ -70,55 +69,107 @@
* by running `ifconfig eth<X> mtu <MTU>' with <X> being the Ethernet
* interface number and <MTU> being the MTU value.
*
+ * Module parameters:
+ *
+ * When compiled as a loadable module, the driver allows for a number
+ * of module parameters to be specified. The driver supports the
+ * following module parameters:
+ *
+ * trace=<val> - Firmware trace level. This requires special traced
+ * firmware to replace the firmware supplied with
+ * the driver - for debugging purposes only.
+ *
+ * link=<val> - Link state. Normally you want to use the default link
+ * parameters set by the driver. This can be used to
+ * override these in case your switch doesn't negotiate
+ * the link properly. Valid values are:
+ * 0x0001 - Force half duplex link.
+ * 0x0002 - Do not negotiate line speed with the other end.
+ * 0x0010 - 10Mbit/sec link.
+ * 0x0020 - 100Mbit/sec link.
+ * 0x0040 - 1000Mbit/sec link.
+ * 0x0100 - Do not negotiate flow control.
+ * 0x0200 - Enable RX flow control Y
+ * 0x0400 - Enable TX flow control Y (Tigon II NICs only).
+ * Default value is 0x0270, ie. enable link+flow
+ * control negotiation. Negotiating the highest
+ * possible link speed with RX flow control enabled.
+ *
+ * When disabling link speed negotiation, only one link
+ * speed is allowed to be specified!
+ *
+ * tx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
+ * to wait for more packets to arive before
+ * interrupting the host, from the time the first
+ * packet arrives.
+ *
+ * rx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
+ * to wait for more packets to arive in the transmit ring,
+ * before interrupting the host, after transmitting the
+ * first packet in the ring.
+ *
+ * max_tx_desc=<val> - maximum number of transmit descriptors
+ * (packets) transmitted before interrupting the host.
+ *
+ * max_rx_desc=<val> - maximum number of receive descriptors
+ * (packets) received before interrupting the host.
+ *
+ * If you use more than one NIC, specify the parameters for the
+ * individual NICs with a comma, ie. trace=0,0x00001fff,0 you want to
+ * run tracing on NIC #2 but not on NIC #1 and #3.
+ *
* TODO:
*
* - Add multicast support.
- * - Make all the tuning parameters and link speed negotiation, user
- * settable at driver/module init time.
+ * - NIC dump support.
+ * - More tuning parameters.
*/
-static const char *version = "acenic.c: v0.13 11/25/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static int link[8] = {0, };
+static int trace[8] = {0, };
+static int tx_coal_tick[8] = {0, };
+static int rx_coal_tick[8] = {0, };
+static int max_tx_desc[8] = {0, };
+static int max_rx_desc[8] = {0, };
+
+static const char *version = "acenic.c: v0.24 01/13/99 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
static struct device *root_dev = NULL;
static int ace_load_firmware(struct device *dev);
+static int probed __initdata = 0;
+
__initfunc(int acenic_probe (struct device *dev))
{
- static int i = 0;
int boards_found = 0;
int version_disp;
- u32 tmp;
struct ace_private *ap;
+ u8 pci_latency;
+#if 0
u16 vendor, device;
u8 pci_bus;
u8 pci_dev_fun;
- u8 pci_latency;
u8 irq;
+#endif
+ struct pci_dev *pdev = NULL;
+
+ if (probed)
+ return -ENODEV;
+ probed ++;
if (!pci_present()) /* is PCI support present? */
return -ENODEV;
version_disp = 0;
- for (; i < 255; i++)
+ while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev)))
{
dev = NULL;
- if (pcibios_find_class(PCI_CLASS_NETWORK_ETHERNET << 8,
- i, &pci_bus, &pci_dev_fun) !=
- PCIBIOS_SUCCESSFUL)
- break;
-
- pcibios_read_config_word(pci_bus, pci_dev_fun,
- PCI_VENDOR_ID, &vendor);
-
- pcibios_read_config_word(pci_bus, pci_dev_fun,
- PCI_DEVICE_ID, &device);
-
- if ((vendor != PCI_VENDOR_ID_ALTEON) &&
- !((vendor == PCI_VENDOR_ID_3COM) &&
- (device == PCI_DEVICE_ID_3COM_3C985)))
+ if ((pdev->vendor != PCI_VENDOR_ID_ALTEON) &&
+ !((pdev->vendor == PCI_VENDOR_ID_3COM) &&
+ (pdev->device == PCI_DEVICE_ID_3COM_3C985)))
continue;
dev = init_etherdev(dev, sizeof(struct ace_private));
@@ -133,36 +184,10 @@ __initfunc(int acenic_probe (struct device *dev))
dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
ap = dev->priv;
- ap->vendor = vendor;
-
- /* Read register base address from
- PCI Configuration Space */
-
- pcibios_read_config_dword(pci_bus, pci_dev_fun,
- PCI_BASE_ADDRESS_0, &tmp);
-
- pcibios_read_config_byte(pci_bus, pci_dev_fun,
- PCI_INTERRUPT_LINE, &irq);
-
- pcibios_read_config_word(pci_bus, pci_dev_fun,
- PCI_COMMAND, &ap->pci_command);
-
- if (!(ap->pci_command & PCI_COMMAND_MASTER)){
- ap->pci_command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pci_bus, pci_dev_fun,
- PCI_COMMAND,
- ap->pci_command);
- }
-
- if (!(ap->pci_command & PCI_COMMAND_MEMORY)){
- printk(KERN_ERR "Shared mem not enabled - "
- "unable to configure AceNIC\n");
- break;
- }
+ ap->pdev = pdev;
+ ap->vendor = pdev->vendor;
- dev->irq = irq;
- ap->pci_bus = pci_bus;
- ap->pci_dev_fun = pci_dev_fun;
+ dev->irq = pdev->irq;
#ifdef __SMP__
spin_lock_init(&ap->lock);
#endif
@@ -189,15 +214,17 @@ __initfunc(int acenic_probe (struct device *dev))
printk(version);
}
- pcibios_read_config_byte(pci_bus, pci_dev_fun,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
+
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency <= 0x40){
pci_latency = 0x40;
- pcibios_write_config_byte(pci_bus, pci_dev_fun,
- PCI_LATENCY_TIMER,
- pci_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
+ pci_latency);
}
+ pci_set_master(pdev);
+
switch(ap->vendor){
case PCI_VENDOR_ID_ALTEON:
sprintf(ap->name, "AceNIC Gigabit Ethernet");
@@ -212,21 +239,27 @@ __initfunc(int acenic_probe (struct device *dev))
printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
break;
}
- printk("Gigabit Ethernet at 0x%08x, irq %i, PCI latency %i "
- "clks\n", tmp, dev->irq, pci_latency);
+ printk("Gigabit Ethernet at 0x%08lx, irq %i, PCI latency %i "
+ "clks\n", pdev->base_address[0], dev->irq, pci_latency);
/*
* Remap the regs into kernel space.
*/
- ap->regs = (struct ace_regs *)ioremap(tmp, 0x4000);
+ ap->regs = (struct ace_regs *)ioremap(pdev->base_address[0],
+ 0x4000);
if (!ap->regs){
printk(KERN_ERR "%s: Unable to map I/O register, "
- "AceNIC %i will be disabled.\n", dev->name, i);
+ "AceNIC %i will be disabled.\n",
+ dev->name, boards_found);
break;
}
- ace_init(dev);
+#ifdef MODULE
+ ace_init(dev, boards_found);
+#else
+ ace_init(dev, -1);
+#endif
boards_found++;
@@ -255,6 +288,17 @@ __initfunc(int acenic_probe (struct device *dev))
#ifdef MODULE
+#if LINUX_VERSION_CODE > 0x20118
+MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
+MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver");
+MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
+#endif
+
int init_module(void)
{
int cards;
@@ -299,6 +343,8 @@ void cleanup_module(void)
}
iounmap(regs);
+ if(ap->trace_buf)
+ kfree(ap->trace_buf);
kfree(ap->info);
free_irq(root_dev->irq, root_dev);
unregister_netdev(root_dev);
@@ -326,12 +372,12 @@ static inline void ace_issue_cmd(struct ace_regs *regs, struct cmd *cmd)
}
-__initfunc(static int ace_init(struct device *dev))
+__initfunc(static int ace_init(struct device *dev, int board_idx))
{
struct ace_private *ap;
struct ace_regs *regs;
struct ace_info *info;
- u32 tig_ver, mac1 = 0, mac2 = 0, tmp;
+ u32 tig_ver, mac1, mac2, tmp;
unsigned long tmp_ptr, myjif;
short i;
@@ -345,7 +391,7 @@ __initfunc(static int ace_init(struct device *dev))
{
long myjif = jiffies + HZ;
- while (myjif > jiffies);
+ while (time_before(jiffies, myjif));
}
#endif
@@ -360,13 +406,6 @@ __initfunc(static int ace_init(struct device *dev))
((CLR_INT | WORD_SWAP) << 24));
#endif
-#ifdef __LITTLE_ENDIAN
- regs->ModeStat = ACE_BYTE_SWAP_DATA | ACE_WARN | ACE_FATAL
- | ACE_WORD_SWAP;
-#else
-#error "this driver doesn't run on big-endian machines yet!"
-#endif
-
/*
* Stop the NIC CPU and clear pending interrupts
*/
@@ -398,10 +437,26 @@ __initfunc(static int ace_init(struct device *dev))
return -ENODEV;
}
+ /*
+ * ModeStat _must_ be set after the SRAM settings as this change
+ * seems to corrupt the ModeStat and possible other registers.
+ * The SRAM settings survive resets and setting it to the same
+ * value a second time works as well. This is what caused the
+ * `Firmware not running' problem on the Tigon II.
+ */
+#ifdef __LITTLE_ENDIAN
+ regs->ModeStat = ACE_BYTE_SWAP_DATA | ACE_WARN | ACE_FATAL
+ | ACE_WORD_SWAP;
+#else
+#error "this driver doesn't run on big-endian machines yet!"
+#endif
+
+ mac1 = 0;
for(i = 0; i < 4; i++){
mac1 = mac1 << 8;
mac1 |= read_eeprom_byte(regs, 0x8c+i);
}
+ mac2 = 0;
for(i = 4; i < 8; i++){
mac2 = mac2 << 8;
mac2 |= read_eeprom_byte(regs, 0x8c+i);
@@ -430,7 +485,14 @@ __initfunc(static int ace_init(struct device *dev))
*/
tmp = READ_CMD_MEM | WRITE_CMD_MEM;
if (ap->version == 2){
+#if 0
+ /*
+ * According to the documentation this enables writes
+ * to all PCI regs - NOT good.
+ */
tmp |= DMA_WRITE_ALL_ALIGN;
+#endif
+ tmp |= MEM_READ_MULTIPLE;
if (ap->pci_command & PCI_COMMAND_INVALIDATE){
switch(L1_CACHE_BYTES){
case 16:
@@ -447,10 +509,8 @@ __initfunc(static int ace_init(struct device *dev))
"supported, PCI write and invalidate "
"disabled\n", L1_CACHE_BYTES);
ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
- pcibios_write_config_word(ap->pci_bus,
- ap->pci_dev_fun,
- PCI_COMMAND,
- ap->pci_command);
+ pci_write_config_word(ap->pdev, PCI_COMMAND,
+ ap->pci_command);
}
}
}
@@ -473,6 +533,13 @@ __initfunc(static int ace_init(struct device *dev))
return -EAGAIN;
}
+ /*
+ * Register the device here to be able to catch allocated
+ * interrupt handlers in case the firmware doesn't come up.
+ */
+ ap->next = root_dev;
+ root_dev = dev;
+
ap->info = info;
memset(info, 0, sizeof(struct ace_info));
@@ -546,41 +613,115 @@ __initfunc(static int ace_init(struct device *dev))
info->tx_csm_ptr = virt_to_bus(&ap->tx_csm);
+ /*
+ * Potential item for tuning parameter
+ */
regs->DmaReadCfg = DMA_THRESH_8W;
regs->DmaWriteCfg = DMA_THRESH_8W;
regs->MaskInt = 0;
regs->IfIdx = 1;
+ regs->AssistState = 1;
#if 0
{
u32 tmp;
- tmp = regs->AssistState;
- tmp &= ~2;
- tmp |= 1;
- regs->AssistState = tmp;
tmp = regs->MacRxState;
tmp &= ~4;
regs->MacRxState = tmp;
}
#endif
+
regs->TuneStatTicks = 2 * TICKS_PER_SEC;
- regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
- regs->TuneMaxTxDesc = 7;
- regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
- regs->TuneMaxRxDesc = 2;
- regs->TuneTrace = 0 /* 0x30001fff */;
- tmp = LNK_ENABLE | LNK_FULL_DUPLEX | LNK_1000MB |
- LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE;
- if(ap->version == 1)
- regs->TuneLink = tmp;
- else{
- tmp |= LNK_TX_FLOW_CTL_Y;
- regs->TuneLink = tmp;
- regs->TuneFastLink = tmp;
+
+ if (board_idx >= 0) {
+ if ((board_idx < 8) && tx_coal_tick[board_idx])
+ regs->TuneTxCoalTicks = tx_coal_tick[board_idx] *
+ TICKS_PER_SEC / 1000;
+ else
+ regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
+ if ((board_idx < 8) && max_tx_desc[board_idx])
+ regs->TuneMaxTxDesc = max_tx_desc[board_idx];
+ else
+ regs->TuneMaxTxDesc = 7;
+
+ if ((board_idx < 8) && rx_coal_tick[board_idx])
+ regs->TuneRxCoalTicks = rx_coal_tick[board_idx] *
+ TICKS_PER_SEC / 1000;
+ else
+ regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
+ if ((board_idx < 8) && max_rx_desc[board_idx])
+ regs->TuneMaxRxDesc = max_rx_desc[board_idx];
+ else
+ regs->TuneMaxRxDesc = 2;
+
+ if (board_idx < 8)
+ regs->TuneTrace = trace[board_idx];
+ else
+ regs->TuneTrace = 0;
+ }else{
+ regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
+ regs->TuneMaxTxDesc = 7;
+ regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
+ regs->TuneMaxRxDesc = 2;
+ regs->TuneTrace = 0;
+ }
+
+ tmp = LNK_ENABLE;
+
+ if ((board_idx > 7) || (board_idx < 0) || !(link[board_idx])){
+ if (board_idx > 7)
+ printk(KERN_WARNING "%s: more then 8 NICs detected, "
+ "ignoring link options!\n", dev->name);
+ /*
+ * No link options specified, we go for the defaults
+ */
+ tmp |= LNK_FULL_DUPLEX | LNK_1000MB | LNK_100MB | LNK_10MB |
+ LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE;
+
+ if(ap->version == 2)
+ tmp |= LNK_TX_FLOW_CTL_Y;
+ } else {
+ int option = link[board_idx];
+
+ if (option & 0x01){
+ printk(KERN_INFO "%s: Setting half duplex link\n",
+ dev->name);
+ tmp |= LNK_FULL_DUPLEX;
+ }
+ if ((option & 0x02) == 0)
+ tmp |= LNK_NEGOTIATE;
+ if (option & 0x10)
+ tmp |= LNK_10MB;
+ if (option & 0x20)
+ tmp |= LNK_100MB;
+ if (option & 0x40)
+ tmp |= LNK_1000MB;
+ if ((option & 0x70) == 0){
+ printk(KERN_WARNING "%s: No media speed specified, "
+ "forcing auto negotiation\n", dev->name);
+ tmp |= LNK_NEGOTIATE | LNK_1000MB |
+ LNK_100MB | LNK_10MB;
+ }
+ if ((option & 0x100) == 0)
+ tmp |= LNK_NEG_FCTL;
+ else
+ printk(KERN_INFO "%s: Disabling flow control "
+ "negotiation\n", dev->name);
+ if (option & 0x200)
+ tmp |= LNK_RX_FLOW_CTL_Y;
+ if ((option & 0x400) && (ap->version == 2)){
+ printk(KERN_INFO "%s: Enabling TX flow control\n",
+ dev->name);
+ tmp |= LNK_TX_FLOW_CTL_Y;
+ }
}
+ regs->TuneLink = tmp;
+ if (ap->version == 2)
+ regs->TuneFastLink = tmp;
+
if (ap->version == 1)
regs->Pc = tigonFwStartAddr;
else if (ap->version == 2)
@@ -595,18 +736,17 @@ __initfunc(static int ace_init(struct device *dev))
regs->CpuCtrl = (regs->CpuCtrl & ~(CPU_HALT | CPU_TRACE));
/*
- * Wait for the firmware to spin up - max 2 seconds.
+ * Wait for the firmware to spin up - max 3 seconds.
*/
myjif = jiffies + 3 * HZ;
- while ((myjif > jiffies) && !ap->fw_running);
+ while (time_before(jiffies, myjif) && !ap->fw_running);
if (!ap->fw_running){
- printk(KERN_ERR "%s: firmware NOT running!\n", dev->name);
+ printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
+ ace_dump_trace(ap);
+ regs->CpuCtrl |= CPU_HALT;
return -EBUSY;
}
- ap->next = root_dev;
- root_dev = dev;
-
/*
* We load the ring here as there seem to be no way to tell the
* firmware to wipe the ring without re-initializing it.
@@ -620,7 +760,6 @@ __initfunc(static int ace_init(struct device *dev))
/*
* Monitor the card to detect hangs.
*/
-
static void ace_timer(unsigned long data)
{
struct device *dev = (struct device *)data;
@@ -643,6 +782,17 @@ static void ace_timer(unsigned long data)
/*
+ * Copy the contents of the NIC's trace buffer to kernel memory.
+ */
+static void ace_dump_trace(struct ace_private *ap)
+{
+ if (!ap->trace_buf)
+ if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL)));
+ return;
+}
+
+
+/*
* Load the standard rx ring.
*/
static int ace_load_std_rx_ring(struct device *dev)
@@ -822,7 +972,6 @@ static u32 ace_handle_event(struct device *dev, u32 evtcsm, u32 evtprd)
ap->fw_running = 1;
break;
case E_STATS_UPDATED:
- mod_timer(&ap->timer, jiffies + (5/2*HZ));
break;
case E_LNK_STATE:
{
@@ -1036,18 +1185,6 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
return;
}
-#if 0
- /*
- * Since we are also using a spinlock, I wonder if this is
- * actually worth it.
- */
- if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) {
- printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n",
- dev->name);
- return;
- }
-#endif
-
/*
* Tell the card not to generate interrupts while we are in here.
*/
@@ -1076,6 +1213,12 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
ap->tx_full = 0;
dev->tbusy = 0;
mark_bh(NET_BH);
+
+ /*
+ * TX ring is no longer full, aka the
+ * transmitter is working fine - kill timer.
+ */
+ del_timer(&ap->timer);
}
ap->tx_ret_csm = txcsm;
@@ -1098,9 +1241,6 @@ static void ace_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
regs->Mb0Lo = 0;
spin_unlock(&ap->lock);
-#if 0
- dev->interrupt = 0;
-#endif
}
@@ -1140,7 +1280,7 @@ static int ace_open(struct device *dev)
#if 0
{ long myjif = jiffies + HZ;
- while (jiffies < myjif);
+ while (time_before(jiffies, myjif));
}
cmd.evt = C_LNK_NEGOTIATION;
@@ -1159,10 +1299,8 @@ static int ace_open(struct device *dev)
* Setup the timer
*/
init_timer(&ap->timer);
- ap->timer.expires = jiffies + 5/2 * HZ;
ap->timer.data = (unsigned long)dev;
- ap->timer.function = &ace_timer;
- add_timer(&ap->timer);
+ ap->timer.function = ace_timer;
return 0;
}
@@ -1239,6 +1377,12 @@ static int ace_start_xmit(struct sk_buff *skb, struct device *dev)
if ((idx + 1) % TX_RING_ENTRIES == ap->tx_ret_csm){
ap->tx_full = 1;
set_bit(0, (void*)&dev->tbusy);
+ /*
+ * Queue is full, add timer to detect whether the
+ * transmitter is stuck.
+ */
+ ap->timer.expires = jiffies + (3 * HZ);
+ add_timer(&ap->timer);
}
spin_unlock_irqrestore(&ap->lock, flags);
@@ -1342,11 +1486,14 @@ static struct net_device_stats *ace_get_stats(struct device *dev)
}
-__initfunc(int ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
+__initfunc(void ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
{
int tsize;
u32 tdest;
+ if (size <= 0)
+ return;
+
while(size > 0){
tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
min(size, ACE_WINDOW_SIZE));
@@ -1365,15 +1512,18 @@ __initfunc(int ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
size -= tsize;
}
- return 0;
+ return;
}
-__initfunc(int ace_clear(struct ace_regs *regs, u32 dest, int size))
+__initfunc(void ace_clear(struct ace_regs *regs, u32 dest, int size))
{
- int tsize;
+ int tsize = 0;
u32 tdest;
+ if (size <= 0)
+ return;
+
while(size > 0){
tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
min(size, ACE_WINDOW_SIZE));
@@ -1386,7 +1536,7 @@ __initfunc(int ace_clear(struct ace_regs *regs, u32 dest, int size))
size -= tsize;
}
- return 0;
+ return;
}
diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h
index e84be5f7b..deca3e895 100644
--- a/drivers/net/acenic.h
+++ b/drivers/net/acenic.h
@@ -142,6 +142,8 @@ struct ace_regs {
#define ACE_JUMBO_MTU 9000
#define ACE_STD_MTU 1500
+#define ACE_TRACE_SIZE 0x8000
+
/*
* Host control register bits.
*/
@@ -205,20 +207,13 @@ struct ace_regs {
#define DMA_WRITE_MAX_128 0xa0
#define DMA_WRITE_MAX_256 0xc0
#define DMA_WRITE_MAX_1K 0xe0
+#define MEM_READ_MULTIPLE 0x00020000
#define DMA_WRITE_ALL_ALIGN 0x00800000
#define READ_CMD_MEM 0x06000000
#define WRITE_CMD_MEM 0x70000000
/*
- * Transmit status.
- */
-
-#define ENA_XMIT 0x01
-#define PERM_CON 0x02
-
-
-/*
* Mode status
*/
@@ -580,12 +575,17 @@ struct ace_private
__attribute__ ((aligned (L1_CACHE_BYTES)));
struct device *next
__attribute__ ((aligned (L1_CACHE_BYTES)));
+ unsigned char *trace_buf;
int fw_running, fw_up, jumbo, promisc;
int version;
- int vendor;
+ int flags;
+ u16 vendor;
u16 pci_command;
+ struct pci_dev *pdev;
+#if 0
u8 pci_bus;
u8 pci_dev_fun;
+#endif
char name[24];
struct net_device_stats stats;
};
@@ -593,7 +593,7 @@ struct ace_private
/*
* Prototypes
*/
-static int ace_init(struct device *dev);
+static int ace_init(struct device *dev, int board_idx);
static int ace_load_std_rx_ring(struct device *dev);
static int ace_load_jumbo_rx_ring(struct device *dev);
static int ace_flush_jumbo_rx_ring(struct device *dev);
@@ -603,6 +603,7 @@ static int ace_open(struct device *dev);
static int ace_start_xmit(struct sk_buff *skb, struct device *dev);
static int ace_close(struct device *dev);
static void ace_timer(unsigned long data);
+static void ace_dump_trace(struct ace_private *ap);
static void ace_set_multicast_list(struct device *dev);
static int ace_change_mtu(struct device *dev, int new_mtu);
static int ace_set_mac_addr(struct device *dev, void *p);
diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h
index 2c7d4f478..7e2472c51 100644
--- a/drivers/net/acenic_firmware.h
+++ b/drivers/net/acenic_firmware.h
@@ -1,28 +1,28 @@
/* Generated by genfw.c */
int tigonFwReleaseMajor = 0xc;
int tigonFwReleaseMinor = 0x1;
-int tigonFwReleaseFix = 0x4;
+int tigonFwReleaseFix = 0x6;
u32 tigonFwStartAddr = 0x4000;
u32 tigonFwTextAddr = 0x4000;
-int tigonFwTextLen = 0x10300;
-u32 tigonFwDataAddr = 0x14d40;
+int tigonFwTextLen = 0x10500;
+u32 tigonFwDataAddr = 0x14f50;
int tigonFwDataLen = 0x140;
-u32 tigonFwRodataAddr = 0x14300;
-int tigonFwRodataLen = 0xa20;
-u32 tigonFwBssAddr = 0x14eb0;
+u32 tigonFwRodataAddr = 0x14500;
+int tigonFwRodataLen = 0xa30;
+u32 tigonFwBssAddr = 0x150c0;
int tigonFwBssLen = 0x2080;
-u32 tigonFwSbssAddr = 0x14e80;
+u32 tigonFwSbssAddr = 0x15090;
int tigonFwSbssLen = 0x28;
-u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
-0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd4d74,
+u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
+0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd4f84,
0x3a0f021, 0x3c100000, 0x26104000, 0xc00100c, 0x0, 0xd,
0x27bdffd8, 0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021, 0x3c170013,
-0x36f75430, 0x2e02021, 0x340583d0, 0xafbf0024, 0xc00242c, 0xafb00020,
-0xc00238c, 0x0, 0x3c040001, 0x24844360, 0x24050001, 0x2e03021,
-0x3821, 0x3c100001, 0x26106f30, 0xafb00010, 0xc0023a7, 0xafbb0014,
+0x36f75430, 0x2e02021, 0x340583d0, 0xafbf0024, 0xc002488, 0xafb00020,
+0xc0023e8, 0x0, 0x3c040001, 0x24844560, 0x24050001, 0x2e03021,
+0x3821, 0x3c100001, 0x26107140, 0xafb00010, 0xc002403, 0xafbb0014,
0x3c02000f, 0x3442ffff, 0x2021024, 0x362102b, 0x10400009, 0x24050003,
-0x3c040001, 0x2484436c, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010,
-0xc0023a7, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821,
+0x3c040001, 0x2484456c, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010,
+0xc002403, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821,
0xa02083a0, 0x3c010001, 0x370821, 0xa02083a2, 0x3c010001, 0x370821,
0xa02083a3, 0x3c010001, 0x370821, 0xac2083a4, 0xa2e004c8, 0x418c0,
0x24840001, 0x771021, 0xac40726c, 0x771021, 0xac407270, 0x2e31021,
@@ -46,122 +46,124 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x8f8200b0, 0x8ee304bc, 0x431025, 0xaf8200b0, 0x8f8200b0, 0x30420004,
0x1440fffd, 0x0, 0x8ee20450, 0x8ee30454, 0xaee304ec, 0x8ee204ec,
0x2442e000, 0x2c422001, 0x1440000d, 0x26e40030, 0x8ee20450, 0x8ee30454,
-0x3c040001, 0x24844378, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704ec,
-0x34a5f000, 0xc0023a7, 0x603021, 0x26e40030, 0xc00242c, 0x24050400,
-0x27440080, 0xc00242c, 0x24050080, 0x26e4776c, 0xc00242c, 0x24050400,
+0x3c040001, 0x24844578, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704ec,
+0x34a5f000, 0xc002403, 0x603021, 0x26e40030, 0xc002488, 0x24050400,
+0x27440080, 0xc002488, 0x24050080, 0x26e4776c, 0xc002488, 0x24050400,
0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260, 0x27450200, 0x24060008,
-0xaee20068, 0x24020006, 0xc00243e, 0xaee20064, 0x3c023b9a, 0x3442ca00,
+0xaee20068, 0x24020006, 0xc00249a, 0xaee20064, 0x3c023b9a, 0x3442ca00,
0x2021, 0x24030002, 0xaee30074, 0xaee30070, 0xaee2006c, 0x240203e8,
0xaee20104, 0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001, 0x641821,
-0x90634d40, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8,
+0x90634f50, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8,
0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030,
0xa062009c, 0x2e41021, 0xa040009c, 0x96e2046a, 0x30420003, 0x14400009,
-0x0, 0x96e2047a, 0x30420003, 0x5040012b, 0x3c030800, 0x96e2046a,
+0x0, 0x96e2047a, 0x30420003, 0x50400131, 0x3c030800, 0x96e2046a,
0x30420003, 0x1040002a, 0x3c020700, 0x96e2047a, 0x30420003, 0x10400026,
0x3c020700, 0x96e3047a, 0x96e2046a, 0x14620022, 0x3c020700, 0x8ee204b0,
0x24030001, 0xa2e34e10, 0x34420e00, 0xaee204b0, 0x8f420218, 0x30420100,
-0x10400005, 0x0, 0x3c020001, 0x2442ded0, 0x800111d, 0x21100,
-0x3c020001, 0x2442d0d0, 0x21100, 0x21182, 0x3c030800, 0x431025,
-0x3c010001, 0xac220f38, 0x3c020001, 0x2442f3c8, 0x21100, 0x21182,
-0x3c030800, 0x431025, 0x3c010001, 0xac220f78, 0x8ee20000, 0x34424000,
-0x8001232, 0xaee20000, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228,
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0,
+0x10400005, 0x0, 0x3c020001, 0x2442e128, 0x800111d, 0x21100,
+0x3c020001, 0x2442d31c, 0x21100, 0x21182, 0x3c030800, 0x431025,
+0x3c010001, 0xac221138, 0x3c020001, 0x2442f640, 0x21100, 0x21182,
+0x3c030800, 0x431025, 0x3c010001, 0xac221178, 0x8ee20000, 0x34424000,
+0x8001238, 0xaee20000, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228,
+0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0,
0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120,
0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0,
-0x800119d, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4,
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001187,
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800119d,
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c,
-0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800121d, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001,
-0xaee201a0, 0x8001201, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0,
+0x3021, 0x24420001, 0xaee201a0, 0x80011a0, 0x8ee201a0, 0x8ee405f8,
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008,
+0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc,
+0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10,
+0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24,
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001,
+0x10a20005, 0x0, 0x800118a, 0x0, 0x14a00005, 0x0,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
+0x50400013, 0xac800000, 0x80011a0, 0x0, 0x8ee24e20, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000,
+0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584,
+0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403,
+0x34a5f000, 0x8001223, 0x0, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001,
+0xaee201a0, 0x8001207, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028,
0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20,
0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24,
-0x24420001, 0x10a20005, 0x0, 0x80011eb, 0x0, 0x14a00005,
+0x24420001, 0x10a20005, 0x0, 0x80011f1, 0x0, 0x14a00005,
0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8001201, 0x0, 0x8ee24e20,
+0x2c420011, 0x50400013, 0xac800000, 0x8001207, 0x0, 0x8ee24e20,
0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001,
0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012,
0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001,
-0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800121d,
-0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228,
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
-0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248443a4, 0x3405f001, 0x24420001,
-0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc0023a7,
-0xafa00014, 0x8001232, 0x0, 0x3c020001, 0x2442f2f0, 0x21100,
-0x21182, 0x431025, 0x3c010001, 0xac220f78, 0x96e2045a, 0x30420003,
+0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
+0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001223,
+0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228,
+0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
+0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248445a4, 0x3405f001, 0x24420001,
+0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc002403,
+0xafa00014, 0x8001238, 0x0, 0x3c020001, 0x2442f568, 0x21100,
+0x21182, 0x431025, 0x3c010001, 0xac221178, 0x96e2045a, 0x30420003,
0x10400025, 0x3c050fff, 0x8ee204b8, 0x34a5ffff, 0x34420a00, 0xaee204b8,
-0x8ee304b8, 0x3c040001, 0x248443b0, 0x24020001, 0xa2e204dc, 0xa2e204dd,
-0x3c020002, 0x621825, 0x3c020001, 0x2442a1c0, 0x451024, 0x21082,
-0xaee304b8, 0x3c030800, 0x431025, 0x3c010001, 0xac220f20, 0x3c020001,
-0x2442abb4, 0x451024, 0x21082, 0x431025, 0x3c010001, 0xac220f80,
-0x96e6045a, 0x3821, 0x24050011, 0xafa00010, 0xc0023a7, 0xafa00014,
-0x8001262, 0x0, 0x3c020001, 0x2442a7e0, 0x21100, 0x21182,
-0x3c030800, 0x431025, 0x3c010001, 0xac220f80, 0x96e2046a, 0x30420010,
-0x14400009, 0x0, 0x96e2047a, 0x30420010, 0x1040010c, 0x0,
+0x8ee304b8, 0x3c040001, 0x248445b0, 0x24020001, 0xa2e204dc, 0xa2e204dd,
+0x3c020002, 0x621825, 0x3c020001, 0x2442a390, 0x451024, 0x21082,
+0xaee304b8, 0x3c030800, 0x431025, 0x3c010001, 0xac221120, 0x3c020001,
+0x2442adb4, 0x451024, 0x21082, 0x431025, 0x3c010001, 0xac221180,
+0x96e6045a, 0x3821, 0x24050011, 0xafa00010, 0xc002403, 0xafa00014,
+0x8001268, 0x0, 0x3c020001, 0x2442a9d4, 0x21100, 0x21182,
+0x3c030800, 0x431025, 0x3c010001, 0xac221180, 0x96e2046a, 0x30420010,
+0x14400009, 0x0, 0x96e2047a, 0x30420010, 0x10400112, 0x0,
0x96e2046a, 0x30420010, 0x10400005, 0x3c020700, 0x96e2047a, 0x30420010,
-0x144000fc, 0x3c020700, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228,
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0,
+0x14400102, 0x3c020700, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228,
+0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0,
0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120,
0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0,
-0x80012e1, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4,
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80012cb,
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80012e1,
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c,
-0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x8001361, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001,
-0xaee201a0, 0x8001345, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0,
+0x3021, 0x24420001, 0xaee201a0, 0x80012ea, 0x8ee201a0, 0x8ee405f8,
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008,
+0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc,
+0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10,
+0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24,
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001,
+0x10a20005, 0x0, 0x80012d4, 0x0, 0x14a00005, 0x0,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
+0x50400013, 0xac800000, 0x80012ea, 0x0, 0x8ee24e20, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000,
+0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584,
+0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403,
+0x34a5f000, 0x800136d, 0x0, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001,
+0xaee201a0, 0x8001351, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028,
0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20,
0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24,
-0x24420001, 0x10a20005, 0x0, 0x800132f, 0x0, 0x14a00005,
+0x24420001, 0x10a20005, 0x0, 0x800133b, 0x0, 0x14a00005,
0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8001345, 0x0, 0x8ee24e20,
+0x2c420011, 0x50400013, 0xac800000, 0x8001351, 0x0, 0x8ee24e20,
0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001,
0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012,
0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001,
-0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001361,
-0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228,
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
-0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248443a4, 0x3405f002, 0x24420001,
-0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc0023a7,
-0xafa00014, 0x96e6047a, 0x96e7046a, 0x3c040001, 0x248443bc, 0x24050012,
-0xafa00010, 0xc0023a7, 0xafa00014, 0xc004440, 0x0, 0xc0022b8,
+0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
+0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800136d,
+0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228,
+0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
+0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248445a4, 0x3405f002, 0x24420001,
+0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc002403,
+0xafa00014, 0x96e6047a, 0x96e7046a, 0x3c040001, 0x248445bc, 0x24050012,
+0xafa00010, 0xc002403, 0xafa00014, 0xc0044c0, 0x0, 0xc002314,
0x0, 0x3c060001, 0x34c63800, 0xaee005f8, 0xaf400228, 0xaf40022c,
0x96e30458, 0x8ee40000, 0x3c0512d8, 0x34a5c358, 0x27623800, 0xaee27248,
0x27623800, 0xaee27250, 0x27623800, 0xaee27254, 0x3661021, 0xaee27260,
@@ -170,464 +172,391 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0xaee05234, 0xaee05230, 0xaee0522c, 0xaee07240, 0xaee07244, 0xaee0724c,
0xaee07258, 0xaee004c0, 0x2463ffff, 0x852025, 0xaee304e8, 0xaee40000,
0xaf800060, 0xaf820064, 0x3c020100, 0xafa20018, 0x8ee205f8, 0x8f430228,
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0,
+0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0,
0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120,
0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0,
-0x8001413, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4,
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80013fd,
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8001413,
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c,
-0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x8001493, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001,
-0xaee201a0, 0x8001477, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0,
+0x3021, 0x24420001, 0xaee201a0, 0x8001422, 0x8ee201a0, 0x8ee405f8,
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008,
+0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc,
+0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10,
+0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24,
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001,
+0x10a20005, 0x0, 0x800140c, 0x0, 0x14a00005, 0x0,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
+0x50400013, 0xac800000, 0x8001422, 0x0, 0x8ee24e20, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000,
+0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584,
+0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403,
+0x34a5f000, 0x80014a5, 0x0, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001,
+0xaee201a0, 0x8001489, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028,
0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20,
0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24,
-0x24420001, 0x10a20005, 0x0, 0x8001461, 0x0, 0x14a00005,
+0x24420001, 0x10a20005, 0x0, 0x8001473, 0x0, 0x14a00005,
0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8001477, 0x0, 0x8ee24e20,
+0x2c420011, 0x50400013, 0xac800000, 0x8001489, 0x0, 0x8ee24e20,
0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001,
0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012,
0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001,
-0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001493,
-0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228,
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
-0x8ee201a8, 0x8ee20150, 0x24420001, 0xaee20150, 0xc0014c8, 0x8ee20150,
+0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
+0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x80014a5,
+0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228,
+0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
+0x8ee201a8, 0x8ee20150, 0x24420001, 0xaee20150, 0xc0014dc, 0x8ee20150,
0x8f8200a0, 0x30420004, 0x1440fffd, 0x0, 0x8f820040, 0x30420001,
0x14400008, 0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0,
0x8f420264, 0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178,
-0x80014b3, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174,
+0x80014c5, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174,
0x24420001, 0xaee20174, 0x8ee20174, 0x8f8200d8, 0x8f8300d4, 0x431023,
0xaee2725c, 0x8ee2725c, 0x1c400003, 0x3c030001, 0x431021, 0xaee2725c,
-0xc003fb0, 0x0, 0xc004380, 0xaf800228, 0x8fbf0024, 0x8fb00020,
+0xc004054, 0x0, 0xc004400, 0xaf800228, 0x8fbf0024, 0x8fb00020,
0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x3e00008, 0x0,
-0x2402002c, 0xaf820050, 0xaee07264, 0x8f420238, 0xaee27268, 0x8f820054,
-0x24420067, 0xaf820058, 0xaee07b78, 0xaee07b7c, 0xaee07b74, 0x3c010001,
-0x370821, 0xac2083ac, 0x3c010001, 0x370821, 0x3e00008, 0xa02083a9,
-0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f820054, 0x3c030001, 0x8c634dfc,
-0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, 0x571021, 0x904283a8,
-0x10400005, 0x3c030200, 0x3c010001, 0x370821, 0x80014ef, 0xa02083a8,
-0x8ee20000, 0x431025, 0xaee20000, 0x8f420218, 0x30420100, 0x104000c3,
-0x0, 0x8f8200b0, 0x30420004, 0x104000bf, 0x0, 0x3c030001,
-0x771821, 0x8c6383c0, 0x8f820104, 0x146200b1, 0x0, 0x3c030001,
-0x771821, 0x8c6383c4, 0x8f8200b4, 0x146200ab, 0x0, 0x8f8200b0,
-0x3c030080, 0x431024, 0x1040000d, 0x0, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, 0xaf8200b0, 0x8f82011c,
-0x2403fffd, 0x431024, 0x80015b5, 0xaf82011c, 0x3c030001, 0x771821,
-0x8c6383c0, 0x8f820104, 0x1462007f, 0x0, 0x3c030001, 0x771821,
-0x8c6383c4, 0x8f8200b4, 0x14620079, 0x0, 0x3c070001, 0xf73821,
-0x8ce783c0, 0x8f8200b0, 0x3c040001, 0x24844430, 0xafa00014, 0xafa20010,
-0x8f8600b0, 0x3c050005, 0xc0023a7, 0x34a50900, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20006, 0x0, 0x8ee201a0, 0x24420001, 0xaee201a0,
-0x8001589, 0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008,
-0x24020400, 0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000,
+0x0, 0x0, 0x2402002c, 0xaf820050, 0xaee07264, 0x8f420238,
+0xaee27268, 0x8f820054, 0x24420067, 0xaf820058, 0xaee07b78, 0xaee07b7c,
+0xaee07b74, 0x3c010001, 0x370821, 0xac2083ac, 0x3c010001, 0x370821,
+0x3e00008, 0xa02083a9, 0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f820054,
+0x3c030001, 0x8c63500c, 0x24420067, 0x1060000d, 0xaf820058, 0x3c020001,
+0x571021, 0x904283a8, 0x10400005, 0x3c030200, 0x3c010001, 0x370821,
+0x8001503, 0xa02083a8, 0x8ee20000, 0x431025, 0xaee20000, 0x8f420218,
+0x30420100, 0x104000c6, 0x0, 0x8f8200b0, 0x30420004, 0x104000c2,
+0x0, 0x3c030001, 0x771821, 0x8c6383c0, 0x8f820104, 0x146200b4,
+0x0, 0x3c030001, 0x771821, 0x8c6383c4, 0x8f8200b4, 0x146200ae,
+0x0, 0x8f8200b0, 0x3c030080, 0x431024, 0x1040000d, 0x0,
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024,
+0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024, 0x80015cc, 0xaf82011c,
+0x3c030001, 0x771821, 0x8c6383c0, 0x8f820104, 0x14620082, 0x0,
+0x3c030001, 0x771821, 0x8c6383c4, 0x8f8200b4, 0x1462007c, 0x0,
+0x3c070001, 0xf73821, 0x8ce783c0, 0x8f8200b0, 0x3c040001, 0x24844630,
+0xafa00014, 0xafa20010, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900,
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001,
+0xaf8200b0, 0xaf830104, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124,
+0x14c20006, 0x0, 0x8ee201a0, 0x24420001, 0xaee201a0, 0x80015a0,
+0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 0x24020400,
+0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 0xac650004,
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x0,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007,
+0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001,
+0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0,
+0x800158a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
+0x80015a0, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003,
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004,
+0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201d4, 0x3c070001,
+0xf73821, 0x8ce783c0, 0x24420001, 0xaee201d4, 0x8ee201d4, 0x3c040001,
+0x2484463c, 0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001, 0x370821,
+0xac2283c0, 0x8f8200b4, 0x3c070001, 0xf73821, 0x8ce783c0, 0x3c040001,
+0x24844644, 0x3c010001, 0x370821, 0xac2283c4, 0xafa00010, 0xafa00014,
+0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x80015cc, 0x0,
+0x8f820104, 0x3c010001, 0x370821, 0xac2283c0, 0x8f8200b4, 0x3c010001,
+0x370821, 0xac2283c4, 0x8ee27264, 0x92e304e4, 0x24420067, 0x14600006,
+0xaee27264, 0x8ee27264, 0x8f430234, 0x43102b, 0x1440007b, 0x0,
+0x8ee304d4, 0x8ee204e8, 0x14620004, 0x0, 0x92e204e4, 0x50400074,
+0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001,
+0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007,
+0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001637,
+0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c,
+0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000,
0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037,
-0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
-0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
+0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
+0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20,
0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005,
-0x0, 0x8001573, 0x0, 0x14a00005, 0x0, 0x8f820128,
+0x0, 0x8001621, 0x0, 0x14a00005, 0x0, 0x8f820128,
0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x8001589, 0x0, 0x8ee24e20, 0x24030040, 0x24420001,
+0xac800000, 0x8001637, 0x0, 0x8ee24e20, 0x24030040, 0x24420001,
0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001,
-0xac820004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201d4,
-0x3c070001, 0xf73821, 0x8ce783c0, 0x24420001, 0xaee201d4, 0x8ee201d4,
-0x3c040001, 0x2484443c, 0x80015a6, 0xafa00010, 0x8f820104, 0x3c010001,
-0x370821, 0xac2283c0, 0x8f8200b4, 0x3c070001, 0xf73821, 0x8ce783c0,
-0x3c040001, 0x24844444, 0x3c010001, 0x370821, 0xac2283c4, 0xafa00010,
-0xafa00014, 0x8f8600b0, 0x3c050005, 0xc0023a7, 0x34a50900, 0x80015b5,
-0x0, 0x8f820104, 0x3c010001, 0x370821, 0xac2283c0, 0x8f8200b4,
-0x3c010001, 0x370821, 0xac2283c4, 0x8ee27264, 0x92e304e4, 0x24420067,
-0x14600006, 0xaee27264, 0x8ee27264, 0x8f430234, 0x43102b, 0x14400078,
-0x0, 0x8ee304d4, 0x8ee204e8, 0x14620004, 0x0, 0x92e204e4,
-0x50400071, 0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0,
-0x8021, 0x24420001, 0xaee201a0, 0x800161d, 0x8ee201a0, 0x8ee204d4,
-0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008,
+0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001,
+0xac820004, 0x5600000b, 0x24100001, 0x8ee204d4, 0x3c040001, 0x2484464c,
+0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403,
+0x34a5f006, 0x16000003, 0x24020001, 0x8001650, 0xa2e204e4, 0x8ee2016c,
+0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0,
+0xaee07264, 0xaee204e8, 0x8ee20e0c, 0x1040006d, 0x0, 0x8f830120,
+0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
+0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0,
+0x8021, 0x24420001, 0xaee201a0, 0x80016ad, 0x8ee201a0, 0x8ee2723c,
+0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008,
0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4,
0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20,
0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f,
0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001607,
+0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001697,
0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800161d,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80016ad,
0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b,
-0x24100001, 0x8ee204d4, 0x3c040001, 0x2484444c, 0xafa00014, 0xafa20010,
-0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f006, 0x16000003,
-0x24020001, 0x8001636, 0xa2e204e4, 0x8ee2016c, 0x24420001, 0xaee2016c,
-0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8,
-0x8ee20e0c, 0x1040006a, 0x0, 0x8f830120, 0x27623800, 0x24660020,
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0,
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001690, 0x8ee201a0,
-0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004,
-0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012,
-0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001,
-0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0,
-0x800167a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8001690, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004,
-0x5600000b, 0x24100001, 0x8ee2723c, 0x3c040001, 0x24844458, 0xafa00014,
-0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008,
-0x56000001, 0xaee00e0c, 0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170,
-0x8ee24e14, 0x10400019, 0x0, 0xaee04e14, 0x8f820040, 0x30420001,
-0x14400008, 0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0,
-0x8f420264, 0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178,
-0x80016bd, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174,
-0x24420001, 0xaee20174, 0x8ee20174, 0x8ee27268, 0x2442ff99, 0xaee27268,
-0x8ee27268, 0x1c400299, 0x0, 0x8f420238, 0x10400296, 0x0,
-0x8f420080, 0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084, 0xaee20038,
-0x8f420084, 0xaee20234, 0x8f420088, 0xaee20238, 0x8f42008c, 0xaee2023c,
-0x8f420090, 0xaee20240, 0x8f420094, 0xaee20244, 0x8f420098, 0xaee20248,
-0x8f42009c, 0xaee2024c, 0x8f4200a0, 0xaee20250, 0x8f4200a4, 0xaee20254,
-0x8f4200a8, 0xaee20258, 0x8f4200ac, 0xaee2025c, 0x8f4200b0, 0xaee20260,
-0x8f4200b4, 0xaee20264, 0x8f4200b8, 0xaee20268, 0x8f4200bc, 0x24040001,
-0xaee2026c, 0xaee0003c, 0x41080, 0x571021, 0x8ee3003c, 0x8c420234,
-0x24840001, 0x621821, 0x2c82000f, 0xaee3003c, 0x1440fff8, 0x41080,
-0x8f4200cc, 0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007,
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001750,
-0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 0x24020400,
-0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 0xac650004,
-0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007,
-0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001,
-0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0,
-0x800173a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8001750, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x12000206, 0x3c020400, 0xafa20018, 0x3c020001, 0x571021, 0x904283a0,
-0x10400105, 0x0, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff,
-0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018,
-0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032,
-0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 0x240f000d,
-0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020,
-0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021,
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80017cb, 0x8ee201a0,
-0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8,
-0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021,
-0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033,
-0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
-0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
-0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
-0x80017b8, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x80017cb, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054,
-0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001,
-0x14620074, 0x3c050009, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032,
-0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 0x240c0011,
-0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020,
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0,
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001834, 0x8ee201a0,
-0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008,
-0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010,
-0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 0x8ee34e20,
-0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 0x8ee24e24,
-0x24420001, 0x10620005, 0x0, 0x8001821, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x8001834, 0x0, 0x8ee24e20,
-0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 0xac8a0004,
-0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9,
-0x0, 0x316300ff, 0x24020001, 0x14620003, 0x3c050009, 0x800194b,
-0x24100001, 0x3c040001, 0x24844464, 0xafa00010, 0xafa00014, 0x8f860120,
-0x8f870124, 0x8001850, 0x34a5f011, 0x3c040001, 0x24844470, 0xafa00010,
-0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, 0xc0023a7, 0x8021,
-0x800194b, 0x0, 0x3c040001, 0x2484447c, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0x8001944, 0x34a5f00f, 0x8ee205f8, 0x8f430228,
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0,
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120,
+0x24100001, 0x8ee2723c, 0x3c040001, 0x24844658, 0xafa00014, 0xafa20010,
+0x8ee6723c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001,
+0xaee00e0c, 0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x8ee24e14,
+0x10400019, 0x0, 0xaee04e14, 0x8f820040, 0x30420001, 0x14400008,
+0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, 0x8f420264,
+0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, 0x80016da,
+0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 0x24420001,
+0xaee20174, 0x8ee20174, 0x8ee27268, 0x2442ff99, 0xaee27268, 0x8ee27268,
+0x1c4002a8, 0x0, 0x8f420238, 0x104002a5, 0x0, 0x8f420080,
+0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084, 0xaee20038, 0x8f420084,
+0xaee20234, 0x8f420088, 0xaee20238, 0x8f42008c, 0xaee2023c, 0x8f420090,
+0xaee20240, 0x8f420094, 0xaee20244, 0x8f420098, 0xaee20248, 0x8f42009c,
+0xaee2024c, 0x8f4200a0, 0xaee20250, 0x8f4200a4, 0xaee20254, 0x8f4200a8,
+0xaee20258, 0x8f4200ac, 0xaee2025c, 0x8f4200b0, 0xaee20260, 0x8f4200b4,
+0xaee20264, 0x8f4200b8, 0xaee20268, 0x8f4200bc, 0x24040001, 0xaee2026c,
+0xaee0003c, 0x41080, 0x571021, 0x8ee3003c, 0x8c420234, 0x24840001,
+0x621821, 0x2c82000f, 0xaee3003c, 0x1440fff8, 0x41080, 0x8f4200cc,
+0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001,
+0xaee201a0, 0x8001770, 0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030,
+0xac620008, 0x24020400, 0xa462000e, 0x2402000f, 0xac620018, 0xac60001c,
+0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10,
+0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24,
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001,
+0x10a20005, 0x0, 0x800175a, 0x0, 0x14a00005, 0x0,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
+0x50400013, 0xac800000, 0x8001770, 0x0, 0x8ee24e20, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000,
+0x24020001, 0xac820004, 0x12000212, 0x3c020400, 0xafa20018, 0x3c020001,
+0x571021, 0x904283a0, 0x1040010b, 0x0, 0x8ee205f8, 0x8f430228,
+0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0,
+0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054,
+0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821,
+0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120,
0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x15020007, 0x1021, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0,
-0x80018c9, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4,
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0,
+0x8021, 0x24420001, 0xaee201a0, 0x80017ee, 0x8ee201a0, 0x8ee405f8,
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f8000e,
+0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008,
+0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 0x24100001,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f,
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007,
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80017db,
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80017ee,
+0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
+0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x14620077,
+0x3c050009, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023,
+0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 0x24080012,
+0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124,
+0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0,
+0x800185a, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494,
+0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004,
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24100001,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f,
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007,
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001847,
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x800185a,
+0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0xac880000, 0xac8a0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
+0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x14620003,
+0x3c050009, 0x8001977, 0x24100001, 0x3c040001, 0x24844664, 0xafa00010,
+0xafa00014, 0x8f860120, 0x8f870124, 0x8001876, 0x34a5f011, 0x3c040001,
+0x24844670, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010,
+0xc002403, 0x8021, 0x8001977, 0x0, 0x3c040001, 0x2484467c,
+0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x8001970, 0x34a5f00f,
+0x8ee205f8, 0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010,
+0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc,
+0xac440600, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001,
+0x27683000, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007,
+0x1021, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80018f2,
+0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004,
+0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c,
+0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010,
+0xaf880120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0,
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
+0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0,
+0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80018dc, 0x0,
+0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80018f2, 0x0,
+0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, 0xaee905f8,
+0x3c040001, 0x24844688, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228,
+0x3c050009, 0xc002403, 0x34a5f000, 0x8001977, 0x0, 0x8f830120,
+0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
+0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0,
+0x8021, 0x24420001, 0xaee201a0, 0x8001959, 0x8ee201a0, 0x8ee205f8,
+0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008,
+0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4,
+0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f,
0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80018b3,
+0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001943,
0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80018c9,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8001959,
0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c,
-0xaee905f8, 0x3c040001, 0x24844488, 0xafa00010, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800194b, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001,
-0xaee201a0, 0x800192d, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
-0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
-0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
-0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20,
-0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24,
-0x24420001, 0x10a20005, 0x0, 0x8001917, 0x0, 0x14a00005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x800192d, 0x0, 0x8ee24e20,
-0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001,
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012,
-0xac820000, 0x24020001, 0xac820004, 0x5600001d, 0x24100001, 0x3c040001,
-0x24844490, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800194b,
-0x8ee201ac, 0x3c040001, 0x2484449c, 0xafa00014, 0x8ee605f8, 0x8f470228,
-0x3c050009, 0x34a5f005, 0xc0023a7, 0x0, 0x8ee201a8, 0x8021,
-0x24420001, 0xaee201a8, 0x8ee201a8, 0x1200000c, 0x24020001, 0x3c010001,
-0x370821, 0xa02083a0, 0x8f420238, 0x8ee30154, 0x24630001, 0xaee30154,
-0x8ee30154, 0x800195b, 0xaee27268, 0x24020001, 0x3c010001, 0x370821,
-0xa02283a0, 0x3c020001, 0x8c424dfc, 0x10400181, 0x0, 0x8ee27b74,
-0x24430001, 0x284200c9, 0x1440019e, 0xaee37b74, 0x8ee204c4, 0x30420002,
-0x14400113, 0xaee07b74, 0x8ee204c4, 0x3c030600, 0x34631000, 0x34420002,
-0xaee204c4, 0xafa30018, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff,
-0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018,
-0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032,
-0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 0x240f000d,
-0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020,
-0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021,
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80019e1, 0x8ee201a0,
-0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8,
-0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021,
-0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033,
-0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
-0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
-0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
-0x80019ce, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x80019e1, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054,
-0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001,
-0x54620075, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032,
-0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 0x240c0011,
-0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020,
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0,
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001a4a, 0x8ee201a0,
-0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008,
-0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010,
-0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 0x8ee34e20,
-0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 0x8ee24e24,
-0x24420001, 0x10620005, 0x0, 0x8001a37, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x8001a4a, 0x0, 0x8ee24e20,
-0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 0xac8a0004,
-0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9,
-0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001,
-0x24844464, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
-0xc0023a7, 0x34a5f011, 0x8001a76, 0x0, 0x3c040001, 0x24844470,
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f010,
-0x8001a76, 0x0, 0x3c040001, 0x2484447c, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 0x24420001,
-0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, 0xaee20158, 0x8ee20158,
-0x8ee204c4, 0x30420001, 0x10400055, 0x0, 0x8f420218, 0x30420080,
-0x10400029, 0x0, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b6c,
-0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 0x2021,
-0x461024, 0x1444000d, 0x671824, 0x1465000b, 0x0, 0x8ee27b70,
-0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 0x14440003,
-0x671824, 0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0,
-0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420020, 0x8001b01,
-0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 0x8001b01, 0xaf820044,
-0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044, 0x8ee27b6c, 0x402821,
-0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 0x2021, 0x461024,
-0x1444000d, 0x671824, 0x1465000b, 0x0, 0x8ee27b70, 0x402821,
-0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 0x14440003, 0x671824,
-0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0, 0x8ee500e4,
-0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420040, 0x8001b01, 0xaf820044,
-0x8f820044, 0x34420040, 0x8001b01, 0xaf820044, 0x8f820044, 0x34420040,
-0xaf820044, 0x8ee27b7c, 0x24430001, 0x28420015, 0x14400028, 0xaee37b7c,
-0x8f820044, 0x38420020, 0xaf820044, 0x8001b01, 0xaee07b7c, 0x8ee204c4,
-0x30420001, 0x10400011, 0x0, 0x8f420218, 0x30420080, 0x10400009,
-0x0, 0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 0x2403ffbf,
-0x431024, 0x8001aff, 0xaf820044, 0x8f820044, 0x34420060, 0x8001aff,
-0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b78, 0x24430001,
-0x28421389, 0x14400005, 0xaee37b78, 0x8f820044, 0x38420020, 0xaf820044,
-0xaee07b78, 0xc0044fc, 0x0, 0x8fbf0024, 0x8fb00020, 0x3e00008,
-0x27bd0028, 0x0, 0x0, 0x0, 0x27bdffb8, 0xafbf0044,
+0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600001d,
+0x24100001, 0x3c040001, 0x24844690, 0xafa00010, 0xafa00014, 0x8ee605f8,
+0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001,
+0xaee201ac, 0x8001977, 0x8ee201ac, 0x3c040001, 0x2484469c, 0xafa00014,
+0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc002403, 0x0,
+0x8ee201a8, 0x8021, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x1200000c,
+0x24020001, 0x3c010001, 0x370821, 0xa02083a0, 0x8f420238, 0x8ee30154,
+0x24630001, 0xaee30154, 0x8ee30154, 0x8001987, 0xaee27268, 0x24020001,
+0x3c010001, 0x370821, 0xa02283a0, 0x3c020001, 0x8c42500c, 0x10400187,
+0x0, 0x8ee27b74, 0x24430001, 0x284200c9, 0x144001a4, 0xaee37b74,
+0x8ee204c4, 0x30420002, 0x14400119, 0xaee07b74, 0x8ee204c4, 0x3c030600,
+0x34631000, 0x34420002, 0xaee204c4, 0xafa30018, 0x8ee205f8, 0x8f430228,
+0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0,
+0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054,
+0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821,
+0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120,
+0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0,
+0x8021, 0x24420001, 0xaee201a0, 0x8001a10, 0x8ee201a0, 0x8ee405f8,
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f8000e,
+0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008,
+0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 0x24100001,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f,
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007,
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80019fd,
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001a10,
+0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
+0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x54620078,
+0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023,
+0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 0x24080012,
+0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124,
+0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0,
+0x8001a7c, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494,
+0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004,
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24100001,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f,
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007,
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001a69,
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001a7c,
+0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0xac880000, 0xac8a0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023,
+0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022,
+0x0, 0x3c040001, 0x24844664, 0xafa00010, 0xafa00014, 0x8f860120,
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001aa8, 0x0,
+0x3c040001, 0x24844670, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
+0xc002403, 0x34a5f010, 0x8001aa8, 0x0, 0x3c040001, 0x2484467c,
+0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f,
+0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001,
+0xaee20158, 0x8ee20158, 0x8ee204c4, 0x30420001, 0x10400055, 0x0,
+0x8f420218, 0x30420080, 0x10400029, 0x0, 0x8f820044, 0x34420040,
+0xaf820044, 0x8ee27b6c, 0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000,
+0x2407ffff, 0x2021, 0x461024, 0x1444000d, 0x671824, 0x1465000b,
+0x0, 0x8ee27b70, 0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021,
+0x461024, 0x14440003, 0x671824, 0x1065000b, 0x0, 0x8ee200c0,
+0x8ee300c4, 0x8ee400e0, 0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044,
+0x38420020, 0x8001b33, 0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024,
+0x8001b33, 0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044,
+0x8ee27b6c, 0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff,
+0x2021, 0x461024, 0x1444000d, 0x671824, 0x1465000b, 0x0,
+0x8ee27b70, 0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024,
+0x14440003, 0x671824, 0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4,
+0x8ee400e0, 0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420040,
+0x8001b33, 0xaf820044, 0x8f820044, 0x34420040, 0x8001b33, 0xaf820044,
+0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b7c, 0x24430001, 0x28420015,
+0x14400028, 0xaee37b7c, 0x8f820044, 0x38420020, 0xaf820044, 0x8001b33,
+0xaee07b7c, 0x8ee204c4, 0x30420001, 0x10400011, 0x0, 0x8f420218,
+0x30420080, 0x10400009, 0x0, 0x8f820044, 0x34420020, 0xaf820044,
+0x8f820044, 0x2403ffbf, 0x431024, 0x8001b31, 0xaf820044, 0x8f820044,
+0x34420060, 0x8001b31, 0xaf820044, 0x8f820044, 0x34420040, 0xaf820044,
+0x8ee27b78, 0x24430001, 0x28421389, 0x14400005, 0xaee37b78, 0x8f820044,
+0x38420020, 0xaf820044, 0xaee07b78, 0xc00457c, 0x0, 0x8fbf0024,
+0x8fb00020, 0x3e00008, 0x27bd0028, 0x0, 0x27bdffb8, 0xafbf0044,
0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, 0xafb20030, 0xafb1002c,
0xafb00028, 0x8f960064, 0x32c20004, 0x1040000c, 0x24020004, 0xaf820064,
0x8f420114, 0xaee204d0, 0x8f820060, 0x34420008, 0xaf820060, 0x8ee20168,
-0x24420001, 0xaee20168, 0x8002293, 0x8ee20168, 0x32c20001, 0x10400004,
-0x24020001, 0xaf820064, 0x8002293, 0x0, 0x32c20002, 0x1040076b,
-0x0, 0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c,
-0x21080, 0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001,
-0x24420001, 0x3042003f, 0x8001b41, 0xaf42022c, 0x3c040001, 0x24844510,
-0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003, 0xc0023a7, 0x34a5f01f,
-0x3821, 0x14e00003, 0x0, 0x800228c, 0xaf960064, 0x93a20020,
-0x2443ffff, 0x2c620011, 0x1040063c, 0x31080, 0x3c010001, 0x220821,
-0x8c2245c8, 0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20dfc,
-0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118,
-0x8002287, 0x8ee20118, 0x8fa20020, 0x24030001, 0x3c010001, 0x370821,
-0xa02383a1, 0x30420fff, 0xaee25228, 0x8f820060, 0x34420100, 0xaf820060,
-0x8ee20144, 0x24420001, 0xaee20144, 0x8002287, 0x8ee20144, 0x8fa20020,
-0x21200, 0x22502, 0x24020001, 0x10820005, 0x24020002, 0x10820009,
-0x2402fffe, 0x8001b8a, 0xafa00010, 0x8ee204c4, 0xaee40070, 0xaee40074,
-0x34420001, 0x8001b7e, 0xaee204c4, 0x8ee304c4, 0xaee40070, 0xaee40074,
-0x621824, 0xaee304c4, 0x8f840054, 0x41442, 0x41c82, 0x431021,
-0x41cc2, 0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023,
-0x8001b91, 0xaee20078, 0x3c040001, 0x2484451c, 0xafa00014, 0x8fa60020,
-0x3c050003, 0xc0023a7, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110,
-0x8002287, 0x8ee20110, 0x27440212, 0xc00229d, 0x24050006, 0x3049001f,
-0x920c0, 0x2e41021, 0x9442726c, 0x30424000, 0x1040000a, 0x971021,
-0x97430212, 0xa443726e, 0x8f430214, 0x971021, 0xac437270, 0x2e41821,
-0x34028000, 0x8001c38, 0xa462726c, 0x9443726e, 0x97420212, 0x14620006,
-0x2e41021, 0x971021, 0x8c437270, 0x8f420214, 0x1062009d, 0x2e41021,
-0x9442726c, 0x30428000, 0x10400028, 0x2406ffff, 0x2021, 0x410c0,
-0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001,
-0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010, 0x620c0, 0x610c0,
-0x571821, 0x8c63736c, 0x571021, 0xafa30010, 0x8c427370, 0x3c040001,
-0x24844528, 0xafa20014, 0x8f470214, 0x3c050003, 0xc0023a7, 0x34a50013,
-0x8001c4f, 0x3c020800, 0x97430212, 0x971021, 0xa443736e, 0x8f430214,
-0x971021, 0xac437370, 0x910c0, 0x2e21021, 0x2e41821, 0x8001c36,
-0xa446726c, 0x2e41021, 0x9445726c, 0x8001bed, 0x510c0, 0x9443736e,
-0x97420212, 0x14620006, 0x510c0, 0x971021, 0x8c437370, 0x8f420214,
-0x10620065, 0x510c0, 0x2e21021, 0x9445736c, 0x510c0, 0x2e21021,
-0x9442736c, 0x30428000, 0x1040fff0, 0x971021, 0x520c0, 0x971021,
-0x9443736e, 0x97420212, 0x14620006, 0x2406ffff, 0x971021, 0x8c437370,
-0x8f420214, 0x10620053, 0x3c020800, 0x2021, 0x410c0, 0x2e21021,
+0x24420001, 0xaee20168, 0x80022ee, 0x8ee20168, 0x32c20001, 0x10400004,
+0x24020001, 0xaf820064, 0x80022ee, 0x0, 0x32c20002, 0x1440000c,
+0x3c050003, 0x3c040001, 0x24844714, 0x34a50001, 0x2c03021, 0x3821,
+0xafa00010, 0xc002403, 0xafa00014, 0x2402fff8, 0x80022ee, 0xaf820064,
+0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, 0x21080,
+0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, 0x24420001,
+0x3042003f, 0x8001b7c, 0xaf42022c, 0x3c040001, 0x24844720, 0xafa00014,
+0x8f46022c, 0x8f47010c, 0x3c050003, 0xc002403, 0x34a5f01f, 0x3821,
+0x14e00003, 0x0, 0x80022e7, 0xaf960064, 0x93a20020, 0x2443ffff,
+0x2c620011, 0x10400656, 0x31080, 0x3c010001, 0x220821, 0x8c2247d8,
+0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20dfc, 0x8f820060,
+0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, 0x80022e2,
+0x8ee20118, 0x8fa20020, 0x24030001, 0x3c010001, 0x370821, 0xa02383a1,
+0x30420fff, 0xaee25228, 0x8f820060, 0x34420100, 0xaf820060, 0x8ee20144,
+0x24420001, 0xaee20144, 0x80022e2, 0x8ee20144, 0x8fa20020, 0x21200,
+0x22502, 0x24020001, 0x10820005, 0x24020002, 0x10820009, 0x2402fffe,
+0x8001bc5, 0xafa00010, 0x8ee204c4, 0xaee40070, 0xaee40074, 0x34420001,
+0x8001bb9, 0xaee204c4, 0x8ee304c4, 0xaee40070, 0xaee40074, 0x621824,
+0xaee304c4, 0x8f840054, 0x41442, 0x41c82, 0x431021, 0x41cc2,
+0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 0x8001bcc,
+0xaee20078, 0x3c040001, 0x2484472c, 0xafa00014, 0x8fa60020, 0x3c050003,
+0xc002403, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, 0x80022e2,
+0x8ee20110, 0x27440212, 0xc0022f8, 0x24050006, 0x3049001f, 0x920c0,
+0x2e41021, 0x9442726c, 0x30424000, 0x1040000a, 0x971021, 0x97430212,
+0xa443726e, 0x8f430214, 0x971021, 0xac437270, 0x2e41821, 0x34028000,
+0x8001c75, 0xa462726c, 0x9443726e, 0x97420212, 0x14620006, 0x2e41021,
+0x971021, 0x8c437270, 0x8f420214, 0x1062009f, 0x2e41021, 0x9442726c,
+0x30428000, 0x1040002a, 0x2406ffff, 0x2021, 0x410c0, 0x2e21021,
0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, 0x2c820080,
-0x1440fff8, 0x410c0, 0x4c10023, 0x620c0, 0x910c0, 0x571821,
-0x8c63726c, 0x571021, 0xafa30010, 0x8c427270, 0x3c040001, 0x24844534,
-0xafa20014, 0x8f470214, 0x3c050003, 0xc0023a7, 0x34a5f017, 0x8001c4f,
-0x3c020800, 0x8f430210, 0xb71021, 0xac43776c, 0x8f430214, 0xb71021,
-0xac437770, 0x3c020001, 0x571021, 0x8c4283a4, 0x24420001, 0x3c010001,
-0x370821, 0xac2283a4, 0x3c030001, 0x771821, 0x8c6383a4, 0x2e51021,
-0x8001c41, 0xa443776c, 0x97430212, 0x971021, 0xa443736e, 0x8f430214,
-0x971021, 0xac437370, 0x510c0, 0x2e21021, 0x2e41821, 0xa446736c,
-0x34028000, 0xa462736c, 0x2021, 0x428c0, 0x2e51021, 0x9442776c,
-0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa, 0x428c0, 0x92e204c8,
-0x10400006, 0x24020001, 0x8ee304cc, 0x1221004, 0x621825, 0x8001c4e,
-0xaee304cc, 0x8f830228, 0x24020001, 0x1221004, 0x621825, 0xaf830228,
-0x3c020800, 0x34421000, 0xafa20018, 0x8ee205f8, 0x8f430228, 0x24420001,
-0x304a00ff, 0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021,
-0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24100008,
-0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800,
-0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007,
-0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001cc4,
-0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
-0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004,
-0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc,
-0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10,
-0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
-0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8001cb1, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x8001cc4, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001,
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff,
-0x24020001, 0x54620075, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240e0008,
-0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007,
-0x0, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001d2d,
-0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c,
-0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4,
-0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f, 0x0,
-0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007, 0x0,
-0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001d1a, 0x0,
-0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d2d, 0x0,
-0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20, 0x24420001,
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8a0000,
-0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
-0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0,
-0x3c040001, 0x24844540, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
-0x3c050009, 0xc0023a7, 0x34a5f011, 0x8001d59, 0x0, 0x3c040001,
-0x2484454c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7,
-0x34a5f010, 0x8001d59, 0x0, 0x3c040001, 0x24844558, 0xafa00014,
-0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8,
-0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20124, 0x24420001, 0xaee20124,
-0x8001f47, 0x8ee20124, 0x27440212, 0xc00229d, 0x24050006, 0x3049001f,
-0x928c0, 0x2e51021, 0x9442726c, 0x30428000, 0x1040002d, 0xb71021,
-0x9443726e, 0x97420212, 0x1462001a, 0xb71021, 0x8c437270, 0x8f420214,
-0x54620018, 0xafa20010, 0x92e204c8, 0x10400007, 0x24020001, 0x8ee304cc,
-0x1221004, 0x21027, 0x621824, 0x8001d7e, 0xaee304cc, 0x8f830228,
-0x1221004, 0x21027, 0x621824, 0xaf830228, 0x918c0, 0x2e31021,
-0x9442726c, 0x2e31821, 0x34424000, 0x8001e04, 0xa462726c, 0x8f420214,
-0xafa20010, 0x910c0, 0x571021, 0x8c42726c, 0x3c040001, 0x24844564,
-0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c, 0xc0023a7, 0x1203021,
-0x8001e39, 0x3c020800, 0x9443726e, 0x97420212, 0x14620019, 0x918c0,
-0xb71021, 0x8c437270, 0x8f420214, 0x14620014, 0x918c0, 0x2e51021,
-0x9447726c, 0x720c0, 0x971021, 0x9443736e, 0xb71021, 0xa443726e,
-0x971021, 0x8c437370, 0xb71021, 0xac437270, 0x2e41021, 0x9443736c,
-0x2e51021, 0xa443726c, 0x2e41821, 0x24024000, 0x8001e04, 0xa462736c,
-0x2e31021, 0x9447726c, 0x3021, 0x720c0, 0x2e41021, 0x9442736c,
-0x4021, 0x30428000, 0x14400025, 0xe02821, 0x605021, 0x240b4000,
-0x971021, 0x9443736e, 0x97420212, 0x54620015, 0xe02821, 0x971021,
-0x8c437370, 0x8f420214, 0x54620010, 0xe02821, 0x11000006, 0x2e41021,
-0x9443736c, 0x510c0, 0x2e21021, 0x8001dd0, 0xa443736c, 0x9443736c,
-0x2ea1021, 0xa443726c, 0x710c0, 0x2e21021, 0xa44b736c, 0x8001dde,
-0x24060001, 0x510c0, 0x2e21021, 0x9447736c, 0x720c0, 0x2e41021,
-0x9442736c, 0x30428000, 0x1040ffdf, 0x25080001, 0x30c200ff, 0x14400025,
-0x2021, 0x720c0, 0x971021, 0x9443736e, 0x97420212, 0x1462000f,
-0x910c0, 0x971021, 0x8c437370, 0x8f420214, 0x1462000a, 0x910c0,
-0x2e41821, 0x24024000, 0x15000015, 0xa462736c, 0x910c0, 0x2e21821,
-0x34028000, 0x8001e04, 0xa462726c, 0x571021, 0x8c42726c, 0x3c040001,
-0x24844570, 0x3c050003, 0xafa20010, 0x710c0, 0x571021, 0x8c42736c,
-0x34a5001e, 0x1203021, 0xc0023a7, 0xafa20014, 0x8001e39, 0x3c020800,
-0x2021, 0x428c0, 0xb71021, 0x9443776e, 0x97420212, 0x5462002b,
-0x24840001, 0xb71021, 0x8c437770, 0x8f420214, 0x54620026, 0x24840001,
-0x3c020001, 0x571021, 0x8c4283a4, 0x2442ffff, 0x3c010001, 0x370821,
-0xac2283a4, 0x3c020001, 0x571021, 0x8c4283a4, 0x809021, 0x242102b,
-0x1040000e, 0x24b1776c, 0x24b07774, 0x2f02021, 0x2f12821, 0xc002434,
-0x24060008, 0x26310008, 0x3c020001, 0x571021, 0x8c4283a4, 0x26520001,
-0x242102b, 0x1440fff5, 0x26100008, 0x3c040001, 0x972021, 0x8c8483a4,
-0x24050008, 0x420c0, 0x2484776c, 0xc00242c, 0x2e42021, 0x8001e39,
-0x3c020800, 0x2c820080, 0x1440ffcf, 0x428c0, 0x3c020800, 0x34422000,
-0xafa20018, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 0x514300f7,
-0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c,
-0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023,
-0x2c420033, 0x10400067, 0x5821, 0x24100008, 0x240f000d, 0x240d0007,
-0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b,
-0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, 0x8ee201a0,
-0x3821, 0x24420001, 0xaee201a0, 0x8001eae, 0x8ee201a0, 0x8ee405f8,
+0x1440fff8, 0x410c0, 0x4c10010, 0x618c0, 0x610c0, 0x571821,
+0x8c63736c, 0x571021, 0xafa30010, 0x8c427370, 0x3c040001, 0x24844738,
+0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a50013, 0x8001c8c,
+0x3c020800, 0x97440212, 0x771021, 0xa444736e, 0x8f440214, 0x771021,
+0x2e31821, 0xac447370, 0x34028000, 0xa462736c, 0x910c0, 0x2e21021,
+0x8001c75, 0xa446726c, 0x2e41021, 0x9445726c, 0x8001c2a, 0x510c0,
+0x9443736e, 0x97420212, 0x14620006, 0x510c0, 0x971021, 0x8c437370,
+0x8f420214, 0x10620065, 0x510c0, 0x2e21021, 0x9445736c, 0x510c0,
+0x2e21021, 0x9442736c, 0x30428000, 0x1040fff0, 0x971021, 0x520c0,
+0x971021, 0x9443736e, 0x97420212, 0x14620006, 0x2406ffff, 0x971021,
+0x8c437370, 0x8f420214, 0x10620053, 0x3c020800, 0x2021, 0x410c0,
+0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001,
+0x2c820080, 0x1440fff8, 0x410c0, 0x4c10023, 0x618c0, 0x910c0,
+0x571821, 0x8c63726c, 0x571021, 0xafa30010, 0x8c427270, 0x3c040001,
+0x24844744, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a5f017,
+0x8001c8c, 0x3c020800, 0x8f430210, 0xb71021, 0xac43776c, 0x8f430214,
+0xb71021, 0xac437770, 0x3c020001, 0x571021, 0x8c4283a4, 0x24420001,
+0x3c010001, 0x370821, 0xac2283a4, 0x3c030001, 0x771821, 0x8c6383a4,
+0x2e51021, 0x8001c7e, 0xa443776c, 0x97440212, 0x771021, 0xa444736e,
+0x8f440214, 0x771021, 0x2e31821, 0xac447370, 0x34028000, 0xa462736c,
+0x510c0, 0x2e21021, 0xa446736c, 0x2021, 0x428c0, 0x2e51021,
+0x9442776c, 0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa, 0x428c0,
+0x92e204c8, 0x10400006, 0x24020001, 0x8ee304cc, 0x1221004, 0x621825,
+0x8001c8b, 0xaee304cc, 0x8f830228, 0x24020001, 0x1221004, 0x621825,
+0xaf830228, 0x3c020800, 0x34421000, 0xafa20018, 0x8ee205f8, 0x8f430228,
+0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0,
+0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054,
+0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821,
+0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120,
+0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0,
+0x3821, 0x24420001, 0xaee201a0, 0x8001d04, 0x8ee201a0, 0x8ee405f8,
0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b,
0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f0000e,
0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008,
@@ -635,707 +564,800 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f,
0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007,
-0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001e9b,
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001cf1,
0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001eae,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d04,
0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20,
0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023,
-0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, 0x54620075,
+0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x54620078,
0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023,
-0x2c420033, 0x1040005e, 0x5821, 0x240e0008, 0x240d0011, 0x240a0012,
+0x2c420033, 0x10400061, 0x5821, 0x240e0008, 0x240d0011, 0x240a0012,
0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0,
-0x3821, 0x24420001, 0xaee201a0, 0x8001f17, 0x8ee201a0, 0x8ee205f8,
-0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e,
-0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
-0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24,
-0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
-0x8ee34e20, 0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001,
-0x10620005, 0x0, 0x8001f04, 0x0, 0x14600005, 0x0,
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
-0x50400010, 0xac800000, 0x8001f17, 0x0, 0x8ee24e20, 0x24420001,
-0x50480003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006,
-0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, 0x0,
-0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, 0x24844540,
-0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7,
-0x34a5f011, 0x8001f43, 0x0, 0x3c040001, 0x2484454c, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f010, 0x8001f43,
-0x0, 0x3c040001, 0x24844558, 0xafa00014, 0x8ee605f8, 0x8f470228,
-0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8,
-0x8ee201a8, 0x8ee20128, 0x24420001, 0xaee20128, 0x8ee20128, 0x8ee20160,
-0x24420001, 0xaee20160, 0x8002287, 0x8ee20160, 0x8fa20020, 0x21200,
-0x21d02, 0x24020001, 0x10620005, 0x24020002, 0x1062000d, 0x0,
-0x8001f67, 0xafa00010, 0x92e204c8, 0x14400006, 0x24020001, 0x8f820228,
-0xaee204cc, 0x2402ffff, 0xaf820228, 0x24020001, 0x8001f6e, 0xa2e204c8,
-0x92e204c8, 0x5040000c, 0xa2e004c8, 0x8ee204cc, 0xaf820228, 0x8001f6e,
-0xa2e004c8, 0x3c040001, 0x24844578, 0xafa00014, 0x8fa60020, 0x3c050003,
-0xc0023a7, 0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c, 0x8002287,
-0x8ee2013c, 0x8fa20020, 0x21200, 0x22502, 0x24020001, 0x10820005,
-0x24020002, 0x1082000f, 0x0, 0x8001f93, 0xafa00010, 0x8f820220,
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001,
-0x3c010001, 0x370821, 0xa02283a2, 0x8001f9a, 0xaee40108, 0x8f820220,
-0x3c0308ff, 0x3463fff7, 0x431024, 0xaf820220, 0x3c010001, 0x370821,
-0xa02083a2, 0x8001f9a, 0xaee40108, 0x3c040001, 0x24844584, 0xafa00014,
-0x8fa60020, 0x3c050003, 0xc0023a7, 0x34a5f00a, 0x8ee2012c, 0x24420001,
-0xaee2012c, 0x8002287, 0x8ee2012c, 0x8fa20020, 0x21200, 0x21d02,
-0x24020001, 0x10620005, 0x24020002, 0x1062000e, 0x0, 0x8001fc1,
-0xafa00010, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008,
-0xaf820220, 0x24020001, 0x3c010001, 0x370821, 0x8001fc8, 0xa02283a3,
-0x3c020001, 0x571021, 0x904283a2, 0x3c010001, 0x370821, 0x1440000e,
-0xa02083a3, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0x8001fc8,
-0xaf820220, 0x3c040001, 0x24844590, 0xafa00014, 0x8fa60020, 0x3c050003,
-0xc0023a7, 0x34a5f00b, 0x8ee20114, 0x24420001, 0xaee20114, 0x8002287,
-0x8ee20114, 0x27840208, 0x27450200, 0xc00243e, 0x24060008, 0x26e40094,
-0x27450200, 0xc00243e, 0x24060008, 0x8ee20134, 0x24420001, 0xaee20134,
-0x8002287, 0x8ee20134, 0x8f460248, 0x24040001, 0xc004e2c, 0x24050004,
-0x8ee20130, 0x24420001, 0xaee20130, 0x8002287, 0x8ee20130, 0x8ef301c4,
-0x8ef401c8, 0x8ef501cc, 0x8ee20140, 0x26e40030, 0x24420001, 0xaee20140,
-0x8ef00140, 0x8ef10074, 0x8ef20070, 0xc00242c, 0x24050400, 0xaef301c4,
-0xaef401c8, 0xaef501cc, 0xaef00140, 0xaef10074, 0xaef20070, 0x8f42025c,
-0x26e40094, 0xaee20060, 0x8f420260, 0x27450200, 0x24060008, 0xaee20068,
-0x24020006, 0xc00243e, 0xaee20064, 0x3c023b9a, 0x3442ca00, 0xaee2006c,
-0x240203e8, 0x24040002, 0x24030001, 0xaee20104, 0xaee40100, 0xaee3010c,
-0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaee30108, 0x8002011,
-0x2021, 0xaee40108, 0x2021, 0x3c030001, 0x641821, 0x90634d50,
-0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0,
-0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c,
-0x2e41021, 0x8002287, 0xa040009c, 0x240a0400, 0x24090040, 0x24080001,
-0x8f830100, 0x27623000, 0x24660020, 0xc2102b, 0x50400001, 0x27662800,
-0x8f820108, 0x14c20007, 0x26e20030, 0x8ee201a4, 0x3821, 0x24420001,
-0xaee201a4, 0x8002050, 0x8ee201a4, 0x8ee404a8, 0x8ee504ac, 0xac620008,
-0xa46a000e, 0xac600018, 0xac60001c, 0xac640000, 0xac650004, 0x8ee204bc,
-0xac620010, 0xaf860100, 0x92e204dc, 0x1440000e, 0x24070001, 0x8ee24e18,
-0x24420001, 0x50490003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18,
-0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21021, 0xac400000, 0xac480004,
-0x10e0ffd5, 0x0, 0x8ee20148, 0x24420001, 0xaee20148, 0x8002287,
-0x8ee20148, 0x3c020900, 0xaee05228, 0xaee0522c, 0xaee05230, 0xaee05234,
-0xaee001c8, 0x3c010001, 0x370821, 0xa02083a1, 0xafa20018, 0x8ee205f8,
-0x8f430228, 0x24420001, 0x304a00ff, 0x514300f7, 0xafa00010, 0x8ee205f8,
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124,
+0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0,
+0x8001d70, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494,
+0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004,
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f,
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007,
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001d5d,
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d70,
+0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023,
+0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022,
+0x0, 0x3c040001, 0x24844750, 0xafa00010, 0xafa00014, 0x8f860120,
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001d9c, 0x0,
+0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
+0xc002403, 0x34a5f010, 0x8001d9c, 0x0, 0x3c040001, 0x24844768,
+0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f,
+0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20124, 0x24420001,
+0xaee20124, 0x8001f93, 0x8ee20124, 0x27440212, 0xc0022f8, 0x24050006,
+0x3049001f, 0x928c0, 0x2e51021, 0x9442726c, 0x30428000, 0x1040002f,
+0x2e51021, 0x9442726c, 0x30424000, 0x1440001c, 0xb71021, 0x9443726e,
+0x97420212, 0x14620018, 0xb71021, 0x8c437270, 0x8f420214, 0x54620016,
+0xafa20010, 0x92e204c8, 0x10400007, 0x24020001, 0x8ee304cc, 0x1221004,
+0x21027, 0x621824, 0x8001dc5, 0xaee304cc, 0x8f830228, 0x1221004,
+0x21027, 0x621824, 0xaf830228, 0x910c0, 0x2e21821, 0x3402c000,
+0x8001e4a, 0xa462726c, 0x8f420214, 0xafa20010, 0x910c0, 0x571021,
+0x8c42726c, 0x3c040001, 0x24844774, 0x3c050003, 0xafa20014, 0x8f470210,
+0x34a5f01c, 0xc002403, 0x1203021, 0x8001e7f, 0x3c020800, 0xb71021,
+0x9443726e, 0x97420212, 0x14620019, 0x918c0, 0xb71021, 0x8c437270,
+0x8f420214, 0x14620014, 0x918c0, 0x2e51021, 0x9447726c, 0x720c0,
+0x971021, 0x9443736e, 0xb71021, 0xa443726e, 0x971021, 0x8c437370,
+0xb71021, 0xac437270, 0x2e41021, 0x9443736c, 0x2e51021, 0xa443726c,
+0x2e41821, 0x3402c000, 0x8001e4a, 0xa462736c, 0x2e31021, 0x9447726c,
+0x3021, 0x720c0, 0x2e41021, 0x9442736c, 0x4021, 0x30428000,
+0x14400025, 0xe02821, 0x605021, 0x340bc000, 0x971021, 0x9443736e,
+0x97420212, 0x54620015, 0xe02821, 0x971021, 0x8c437370, 0x8f420214,
+0x54620010, 0xe02821, 0x11000006, 0x2e41021, 0x9443736c, 0x510c0,
+0x2e21021, 0x8001e16, 0xa443736c, 0x9443736c, 0x2ea1021, 0xa443726c,
+0x710c0, 0x2e21021, 0xa44b736c, 0x8001e24, 0x24060001, 0x510c0,
+0x2e21021, 0x9447736c, 0x720c0, 0x2e41021, 0x9442736c, 0x30428000,
+0x1040ffdf, 0x25080001, 0x30c200ff, 0x14400025, 0x2021, 0x720c0,
+0x971021, 0x9443736e, 0x97420212, 0x1462000f, 0x910c0, 0x971021,
+0x8c437370, 0x8f420214, 0x1462000a, 0x910c0, 0x2e41821, 0x3402c000,
+0x15000015, 0xa462736c, 0x910c0, 0x2e21821, 0x34028000, 0x8001e4a,
+0xa462726c, 0x571021, 0x8c42726c, 0x3c040001, 0x24844780, 0x3c050003,
+0xafa20010, 0x710c0, 0x571021, 0x8c42736c, 0x34a5001e, 0x1203021,
+0xc002403, 0xafa20014, 0x8001e7f, 0x3c020800, 0x2021, 0x428c0,
+0xb71021, 0x9443776e, 0x97420212, 0x5462002b, 0x24840001, 0xb71021,
+0x8c437770, 0x8f420214, 0x54620026, 0x24840001, 0x3c020001, 0x571021,
+0x8c4283a4, 0x2442ffff, 0x3c010001, 0x370821, 0xac2283a4, 0x3c020001,
+0x571021, 0x8c4283a4, 0x809021, 0x242102b, 0x1040000e, 0x24b1776c,
+0x24b07774, 0x2f02021, 0x2f12821, 0xc002490, 0x24060008, 0x26310008,
+0x3c020001, 0x571021, 0x8c4283a4, 0x26520001, 0x242102b, 0x1440fff5,
+0x26100008, 0x3c040001, 0x972021, 0x8c8483a4, 0x24050008, 0x420c0,
+0x2484776c, 0xc002488, 0x2e42021, 0x8001e7f, 0x3c020800, 0x2c820080,
+0x1440ffcf, 0x428c0, 0x3c020800, 0x34422000, 0xafa20018, 0x8ee205f8,
+0x8f430228, 0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8,
0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600,
-0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x10400067,
+0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a,
0x5821, 0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001,
0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000,
-0x8f820128, 0x15020007, 0x1021, 0x8ee201a0, 0x3821, 0x24420001,
-0xaee201a0, 0x80020d4, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821,
-0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xace40000, 0xace50004, 0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c,
-0x210c0, 0x244205fc, 0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010,
-0xaf880120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 0x0, 0x8ee34e20,
-0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004,
-0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 0x0, 0x8ee24e24,
-0x24420001, 0x10620005, 0x0, 0x80020c1, 0x0, 0x14600005,
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400010, 0xac800000, 0x80020d4, 0x0, 0x8ee24e20,
-0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004,
-0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0,
-0x0, 0x316300ff, 0x24020001, 0x54620075, 0xafa00010, 0xaeea05f8,
-0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040005e,
-0x5821, 0x240e0008, 0x240d0011, 0x240a0012, 0x24080040, 0x240c0001,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001,
-0xaee201a0, 0x800213d, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
+0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021,
+0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001ef7, 0x8ee201a0,
+0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8,
+0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021,
+0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033,
+0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
+0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
+0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
+0x8001ee4, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
+0x8001ef7, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021,
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 0x8f820054,
+0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001,
+0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032,
+0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240e0008, 0x240d0011,
+0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001,
+0xaee201a0, 0x8001f63, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000,
0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033,
0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
0x10480007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
-0x800212a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0x8001f50, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
-0x800213d, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021,
+0x8001f63, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021,
0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054,
-0x1221023, 0x2c420033, 0x1440ffa9, 0x0, 0x316300ff, 0x24020001,
-0x10620022, 0x0, 0x3c040001, 0x24844540, 0xafa00010, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f011, 0x8002169,
-0x0, 0x3c040001, 0x2484454c, 0xafa00014, 0x8f860120, 0x8f870124,
-0x3c050009, 0xc0023a7, 0x34a5f010, 0x8002169, 0x0, 0x3c040001,
-0x24844558, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7,
-0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20120,
-0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20164, 0x24420001, 0xaee20164,
-0x8002287, 0x8ee20164, 0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260,
-0x27450200, 0x24060008, 0xc00243e, 0xaee20068, 0x8f820220, 0x30420008,
-0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001,
-0xaee2011c, 0x8002287, 0x8ee2011c, 0x3c040001, 0x2484459c, 0xafa00010,
-0xafa00014, 0x8fa60020, 0x3c050003, 0xc0023a7, 0x34a5f00f, 0x93a20020,
-0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee205f8, 0x8f430228,
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0,
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120,
-0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128,
-0x15020007, 0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0,
-0x80021ff, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430,
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018,
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4,
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f,
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80021e9,
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80021ff,
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54e0000c,
-0xaee905f8, 0x3c040001, 0x248445a4, 0xafa00010, 0xafa00014, 0x8ee605f8,
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800227f, 0x0,
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001,
-0xaee201a0, 0x8002263, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
-0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
-0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
+0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001,
+0x10620022, 0x0, 0x3c040001, 0x24844750, 0xafa00010, 0xafa00014,
+0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001f8f,
+0x0, 0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 0x8f870124,
+0x3c050009, 0xc002403, 0x34a5f010, 0x8001f8f, 0x0, 0x3c040001,
+0x24844768, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403,
+0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20128,
+0x24420001, 0xaee20128, 0x8ee20128, 0x8ee20160, 0x24420001, 0xaee20160,
+0x80022e2, 0x8ee20160, 0x8fa20020, 0x21200, 0x21d02, 0x24020001,
+0x10620005, 0x24020002, 0x1062000d, 0x0, 0x8001fb3, 0xafa00010,
+0x92e204c8, 0x14400006, 0x24020001, 0x8f820228, 0xaee204cc, 0x2402ffff,
+0xaf820228, 0x24020001, 0x8001fba, 0xa2e204c8, 0x92e204c8, 0x5040000c,
+0xa2e004c8, 0x8ee204cc, 0xaf820228, 0x8001fba, 0xa2e004c8, 0x3c040001,
+0x24844788, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f009,
+0x8ee2013c, 0x24420001, 0xaee2013c, 0x80022e2, 0x8ee2013c, 0x8fa20020,
+0x21200, 0x22502, 0x24020001, 0x10820005, 0x24020002, 0x1082000f,
+0x0, 0x8001fdf, 0xafa00010, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420008, 0xaf820220, 0x24020001, 0x3c010001, 0x370821,
+0xa02283a2, 0x8001fe6, 0xaee40108, 0x8f820220, 0x3c0308ff, 0x3463fff7,
+0x431024, 0xaf820220, 0x3c010001, 0x370821, 0xa02083a2, 0x8001fe6,
+0xaee40108, 0x3c040001, 0x24844794, 0xafa00014, 0x8fa60020, 0x3c050003,
+0xc002403, 0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c, 0x80022e2,
+0x8ee2012c, 0x8fa20020, 0x21200, 0x21d02, 0x24020001, 0x10620005,
+0x24020002, 0x1062000e, 0x0, 0x800200d, 0xafa00010, 0x8f820220,
+0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001,
+0x3c010001, 0x370821, 0x8002014, 0xa02283a3, 0x3c020001, 0x571021,
+0x904283a2, 0x3c010001, 0x370821, 0x1440000e, 0xa02083a3, 0x8f820220,
+0x3c0308ff, 0x3463fff7, 0x431024, 0x8002014, 0xaf820220, 0x3c040001,
+0x248447a0, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00b,
+0x8ee20114, 0x24420001, 0xaee20114, 0x80022e2, 0x8ee20114, 0x27840208,
+0x27450200, 0xc00249a, 0x24060008, 0x26e40094, 0x27450200, 0xc00249a,
+0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, 0x80022e2, 0x8ee20134,
+0x8f460248, 0x24040001, 0xc004eac, 0x24050004, 0x8ee20130, 0x24420001,
+0xaee20130, 0x80022e2, 0x8ee20130, 0x8ef301c4, 0x8ef401c8, 0x8ef501cc,
+0x8ee20140, 0x26e40030, 0x24420001, 0xaee20140, 0x8ef00140, 0x8ef10074,
+0x8ef20070, 0xc002488, 0x24050400, 0xaef301c4, 0xaef401c8, 0xaef501cc,
+0xaef00140, 0xaef10074, 0xaef20070, 0x8f42025c, 0x26e40094, 0xaee20060,
+0x8f420260, 0x27450200, 0x24060008, 0xaee20068, 0x24020006, 0xc00249a,
+0xaee20064, 0x3c023b9a, 0x3442ca00, 0xaee2006c, 0x240203e8, 0x24040002,
+0x24030001, 0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220, 0x30420008,
+0x10400004, 0x0, 0xaee30108, 0x800205d, 0x2021, 0xaee40108,
+0x2021, 0x3c030001, 0x641821, 0x90634f60, 0x2e41021, 0x24840001,
+0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821,
+0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, 0x80022e2,
+0xa040009c, 0x240a0400, 0x24090040, 0x24080001, 0x8f830100, 0x27623000,
+0x24660020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004,
+0x0, 0x8f820104, 0x14c20007, 0x26e20030, 0x8ee201a4, 0x3821,
+0x24420001, 0xaee201a4, 0x800209f, 0x8ee201a4, 0x8ee404a8, 0x8ee504ac,
+0xac620008, 0xa46a000e, 0xac600018, 0xac60001c, 0xac640000, 0xac650004,
+0x8ee204bc, 0xac620010, 0xaf860100, 0x92e204dc, 0x1440000e, 0x24070001,
+0x8ee24e18, 0x24420001, 0x50490003, 0x1021, 0x8ee24e18, 0x24420001,
+0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21021, 0xac400000,
+0xac480004, 0x10e0ffd2, 0x0, 0x8ee20148, 0x24420001, 0xaee20148,
+0x80022e2, 0x8ee20148, 0x3c020900, 0xaee05228, 0xaee0522c, 0xaee05230,
+0xaee05234, 0xaee001c8, 0x3c010001, 0x370821, 0xa02083a1, 0xafa20018,
+0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010,
+0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc,
+0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033,
+0x1040006a, 0x5821, 0x24100008, 0x240f000d, 0x240d0007, 0x240c0040,
+0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001,
+0x27683000, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007,
+0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8002126,
+0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004,
+0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc,
+0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10,
+0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
+0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
+0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
+0x0, 0x8002113, 0x0, 0x14600005, 0x0, 0x8f820128,
+0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
+0xac800000, 0x8002126, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003,
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001,
+0x8f820054, 0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff,
+0x24020001, 0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054,
+0x24690032, 0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240e0008,
+0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800,
+0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
+0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821,
+0x24420001, 0xaee201a0, 0x8002192, 0x8ee201a0, 0x8ee205f8, 0xac62001c,
+0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018,
+0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10,
+0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
+0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
+0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
+0x0, 0x800217f, 0x0, 0x14600005, 0x0, 0x8f820128,
+0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
+0xac800000, 0x8002192, 0x0, 0x8ee24e20, 0x24420001, 0x50480003,
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001,
+0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff,
+0x24020001, 0x10620022, 0x0, 0x3c040001, 0x24844750, 0xafa00010,
+0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011,
+0x80021be, 0x0, 0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120,
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80021be, 0x0,
+0x3c040001, 0x24844768, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
+0xc002403, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8,
+0x8ee20120, 0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20164, 0x24420001,
+0xaee20164, 0x80022e2, 0x8ee20164, 0x8f42025c, 0x26e40094, 0xaee20060,
+0x8f420260, 0x27450200, 0x24060008, 0xc00249a, 0xaee20068, 0x8f820220,
+0x30420008, 0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c,
+0x24420001, 0xaee2011c, 0x80022e2, 0x8ee2011c, 0x3c040001, 0x248447ac,
+0xafa00010, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00f,
+0x93a20020, 0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee205f8,
+0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8,
+0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600,
+0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000,
+0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021,
+0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8002257, 0x8ee201a0,
+0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8,
+0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0,
+0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120,
0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20,
+0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20,
0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24,
-0x24420001, 0x10a20005, 0x0, 0x800224d, 0x0, 0x14a00005,
+0x24420001, 0x10a20005, 0x0, 0x8002241, 0x0, 0x14a00005,
0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x8002263, 0x0, 0x8ee24e20,
+0x2c420011, 0x50400013, 0xac800000, 0x8002257, 0x0, 0x8ee24e20,
0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001,
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012,
-0xac820000, 0x24020001, 0xac820004, 0x14e0001b, 0x0, 0x3c040001,
-0x248445ac, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800227f,
-0x8ee201ac, 0x3c040001, 0x248445b8, 0xafa00014, 0x8ee605f8, 0x8f470228,
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8,
-0x8ee201a8, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x8ee2014c, 0x8ee2015c,
-0x24420001, 0xaee2015c, 0x8ee2015c, 0x8f43022c, 0x8f42010c, 0x14620009,
-0x24020002, 0xaf820064, 0x8f820064, 0x14400005, 0x0, 0x8f43022c,
-0x8f42010c, 0x1462f897, 0x0, 0x8fbf0044, 0x8fb60040, 0x8fb5003c,
-0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x3e00008,
-0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8,
-0x354a8320, 0x90870000, 0x24840001, 0x3021, 0x1071026, 0x30420001,
-0x10400002, 0x81842, 0x6a1826, 0x604021, 0x24c60001, 0x2cc20008,
-0x1440fff7, 0x73842, 0x25290001, 0x125102b, 0x1440fff0, 0x0,
-0x1001021, 0x3e00008, 0x27bd0008, 0x0, 0x27bdffe8, 0x27642800,
-0xafbf0010, 0xc00242c, 0x24051000, 0x24020021, 0xaf800100, 0xaf800104,
-0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118, 0xaf800120, 0xaf800124,
-0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138, 0xaee04e18, 0xaee04e1c,
-0xaee04e20, 0xaee04e24, 0xaf82011c, 0x8f420218, 0x30420040, 0x10400004,
-0x0, 0x8f82011c, 0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010, 0x8f820100,
-0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, 0x3c040001, 0x2484466c,
-0xc0023a7, 0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824, 0x3c020400,
-0x1062002b, 0x43102b, 0x14400008, 0x3c022000, 0x3c020100, 0x10620026,
-0x3c020200, 0x10620013, 0x0, 0x8002316, 0x0, 0x1062000a,
-0x43102b, 0x1040001e, 0x3c024000, 0x1462001c, 0x0, 0x8ee2018c,
-0x24420001, 0xaee2018c, 0x8002316, 0x8ee2018c, 0x8ee20188, 0x24420001,
-0xaee20188, 0x8002316, 0x8ee20188, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f82011c,
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee2019c, 0x24420001, 0xaee2019c,
-0x8002319, 0x8ee2019c, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018,
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820120,
-0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, 0x8f8600a0, 0x8f87011c,
-0x3c040001, 0x24844678, 0xc0023a7, 0x34a5f000, 0x8f8300a0, 0x3c027f00,
-0x621824, 0x3c020400, 0x10620055, 0x8021, 0x43102b, 0x14400008,
-0x3c042000, 0x3c020100, 0x1062004f, 0x3c020200, 0x1062003c, 0x0,
-0x8002384, 0x0, 0x10640005, 0x83102b, 0x10400047, 0x3c024000,
-0x14620045, 0x0, 0x8f8200a0, 0x441024, 0x10400006, 0x0,
-0x8ee20190, 0x24420001, 0xaee20190, 0x800234d, 0x8ee20190, 0x8ee20194,
-0x24420001, 0xaee20194, 0x8ee20194, 0x8f82011c, 0x34420002, 0xaf82011c,
-0x8f82011c, 0x30420200, 0x1040001b, 0x0, 0x8f8300a0, 0x8f840124,
-0x8f8200ac, 0x14400007, 0x24020001, 0x3c020001, 0x3442f000, 0x621024,
-0x50400001, 0x24100001, 0x24020001, 0x1200000d, 0xaf8200a0, 0x8f820124,
-0x2442ffe0, 0xaf820124, 0x8f820124, 0x8f820124, 0x27633000, 0x43102b,
-0x10400005, 0x276237e0, 0xaf820124, 0x800236e, 0x0, 0xaf840124,
-0x8f82011c, 0x2403fffd, 0x431024, 0x8002387, 0xaf82011c, 0x8f82011c,
-0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0,
-0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee20198,
-0x24420001, 0xaee20198, 0x8002387, 0x8ee20198, 0x8f8200a0, 0x34420001,
-0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x0,
-0x3c020001, 0x8c424d78, 0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb00010,
-0x3c100001, 0x26104eb0, 0x2002021, 0xc00242c, 0x24052000, 0x26021fe0,
-0x3c010001, 0xac224e84, 0x3c010001, 0xac224e80, 0xaf420250, 0x24022000,
-0xaf500254, 0xaf420258, 0x24020001, 0x3c010001, 0xac224d78, 0x8fbf0014,
-0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c030001, 0x8c634e84, 0x8c820000,
-0x8fa80010, 0x8fa90014, 0xac620000, 0x3c020001, 0x8c424e84, 0x8c830004,
-0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014,
-0xac480018, 0xac49001c, 0x3c010001, 0xac234e84, 0xac44000c, 0x3c020001,
-0x24424eb0, 0x62182b, 0x10600005, 0x0, 0x3c020001, 0x8c424e80,
-0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60,
-0xac620000, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 0xac620004,
-0x3e00008, 0xaf430250, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60,
-0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, 0x808021, 0xafb50024,
-0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, 0xafbf0028, 0xafb3001c,
-0xafb20018, 0xac620000, 0x3c050001, 0x8ca54e84, 0x3c020001, 0x8c424d60,
-0xc09021, 0xe09821, 0x10800006, 0xaca20004, 0x24a50008, 0xc002434,
-0x24060018, 0x80023f2, 0x0, 0x24a40008, 0xc00242c, 0x24050018,
-0x3c020001, 0x8c424e84, 0x3c050001, 0x24a54eb0, 0x2442ffe0, 0x3c010001,
-0xac224e84, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c424e80,
-0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x8e020000, 0xac620000,
-0x3c030001, 0x8c634e84, 0x8e020004, 0xac620004, 0xac710008, 0x8f840054,
-0x2462ffe0, 0x3c010001, 0xac224e84, 0x45102b, 0xac720010, 0xac730014,
-0xac740018, 0xac75001c, 0x10400005, 0xac64000c, 0x3c020001, 0x8c424e80,
-0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60,
-0xac620000, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 0xac620004,
-0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005, 0x0,
-0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 0x3e00008, 0x0,
-0x10c00007, 0x0, 0x8c820000, 0x24840004, 0x24c6fffc, 0xaca20000,
-0x14c0fffb, 0x24a50004, 0x3e00008, 0x0, 0x10c00007, 0x0,
-0x8ca20000, 0x24a50004, 0x24c6fffc, 0xac820000, 0x14c0fffb, 0x24840004,
-0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0020,
-0x8ee304d4, 0x8ee204d0, 0x1062041e, 0x0, 0x8ee204d4, 0x8ee304ec,
-0x21100, 0x626021, 0x95870008, 0x8d8a0000, 0x8d8b0004, 0x958d000a,
-0x8ee2724c, 0x8ee3725c, 0x30e4ffff, 0x441021, 0x62182b, 0x10600015,
-0x31a20004, 0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 0x8ee2725c,
-0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, 0x8ee2724c, 0x8ee3725c,
-0x441021, 0x62182b, 0x10600006, 0x31a20004, 0x8ee201b4, 0x24420001,
-0xaee201b4, 0x800286d, 0x8ee201b4, 0x10400234, 0x31a20200, 0x10400144,
-0x4821, 0x96e2045a, 0x30420010, 0x10400140, 0x0, 0x8f840100,
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007,
+0xac820000, 0x24020001, 0xac820004, 0x54e0000c, 0xaee905f8, 0x3c040001,
+0x248447b4, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
+0xc002403, 0x34a5f000, 0x80022da, 0x0, 0x8f830120, 0x27623800,
+0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004,
+0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821,
+0x24420001, 0xaee201a0, 0x80022be, 0x8ee201a0, 0x8ee205f8, 0xac62001c,
+0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e,
+0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010,
+0xaf860120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0,
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
+0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0,
+0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80022a8, 0x0,
+0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80022be, 0x0,
+0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20,
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14e0001b, 0x0,
+0x3c040001, 0x248447bc, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228,
+0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac,
+0x80022da, 0x8ee201ac, 0x3c040001, 0x248447c8, 0xafa00014, 0x8ee605f8,
+0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001,
+0xaee201a8, 0x8ee201a8, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x8ee2014c,
+0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, 0x8f43022c, 0x8f42010c,
+0x14620009, 0x24020002, 0xaf820064, 0x8f820064, 0x14400005, 0x0,
+0x8f43022c, 0x8f42010c, 0x1462f877, 0x0, 0x8fbf0044, 0x8fb60040,
+0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028,
+0x3e00008, 0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821,
+0x3c0aedb8, 0x354a8320, 0x90870000, 0x24840001, 0x3021, 0x1071026,
+0x30420001, 0x10400002, 0x81842, 0x6a1826, 0x604021, 0x24c60001,
+0x2cc20008, 0x1440fff7, 0x73842, 0x25290001, 0x125102b, 0x1440fff0,
+0x0, 0x1001021, 0x3e00008, 0x27bd0008, 0x0, 0x0,
+0x27bdffe8, 0x27642800, 0xafbf0010, 0xc002488, 0x24051000, 0x24020021,
+0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118,
+0xaf800120, 0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138,
+0xaee04e18, 0xaee04e1c, 0xaee04e20, 0xaee04e24, 0xaf82011c, 0x8f420218,
+0x30420040, 0x10400004, 0x0, 0x8f82011c, 0x34420004, 0xaf82011c,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104,
+0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c,
+0x3c040001, 0x2484487c, 0xc002403, 0x34a5f000, 0x8f8300b0, 0x3c027f00,
+0x621824, 0x3c020400, 0x1062002b, 0x43102b, 0x14400008, 0x3c022000,
+0x3c020100, 0x10620026, 0x3c020200, 0x10620013, 0x0, 0x8002372,
+0x0, 0x1062000a, 0x43102b, 0x1040001e, 0x3c024000, 0x1462001c,
+0x0, 0x8ee2018c, 0x24420001, 0xaee2018c, 0x8002372, 0x8ee2018c,
+0x8ee20188, 0x24420001, 0xaee20188, 0x8002372, 0x8ee20188, 0x8f82011c,
+0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0,
+0xaf830104, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee2019c,
+0x24420001, 0xaee2019c, 0x8002375, 0x8ee2019c, 0x8f8200b0, 0x34420001,
+0xaf8200b0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf001c,
+0xafb00018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014,
+0x8f8600a0, 0x8f87011c, 0x3c040001, 0x24844888, 0xc002403, 0x34a5f000,
+0x8f8300a0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620055, 0x8021,
+0x43102b, 0x14400008, 0x3c042000, 0x3c020100, 0x1062004f, 0x3c020200,
+0x1062003c, 0x0, 0x80023e0, 0x0, 0x10640005, 0x83102b,
+0x10400047, 0x3c024000, 0x14620045, 0x0, 0x8f8200a0, 0x441024,
+0x10400006, 0x0, 0x8ee20190, 0x24420001, 0xaee20190, 0x80023a9,
+0x8ee20190, 0x8ee20194, 0x24420001, 0xaee20194, 0x8ee20194, 0x8f82011c,
+0x34420002, 0xaf82011c, 0x8f82011c, 0x30420200, 0x1040001b, 0x0,
+0x8f8300a0, 0x8f840124, 0x8f8200ac, 0x14400007, 0x24020001, 0x3c020001,
+0x3442f000, 0x621024, 0x50400001, 0x24100001, 0x24020001, 0x1200000d,
+0xaf8200a0, 0x8f820124, 0x2442ffe0, 0xaf820124, 0x8f820124, 0x8f820124,
+0x27633000, 0x43102b, 0x10400005, 0x276237e0, 0xaf820124, 0x80023ca,
+0x0, 0xaf840124, 0x8f82011c, 0x2403fffd, 0x431024, 0x80023e3,
+0xaf82011c, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0,
+0x34420001, 0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024,
+0xaf82011c, 0x8ee20198, 0x24420001, 0xaee20198, 0x80023e3, 0x8ee20198,
+0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008,
+0x27bd0020, 0x0, 0x3c020001, 0x8c424f88, 0x27bdffe8, 0xafbf0014,
+0x14400012, 0xafb00010, 0x3c100001, 0x261050c0, 0x2002021, 0xc002488,
+0x24052000, 0x26021fe0, 0x3c010001, 0xac225094, 0x3c010001, 0xac225090,
+0xaf420250, 0x24022000, 0xaf500254, 0xaf420258, 0x24020001, 0x3c010001,
+0xac224f88, 0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c030001,
+0x8c635094, 0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000, 0x3c020001,
+0x8c425094, 0x8c830004, 0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0,
+0xac460010, 0xac470014, 0xac480018, 0xac49001c, 0x3c010001, 0xac235094,
+0xac44000c, 0x3c020001, 0x244250c0, 0x62182b, 0x10600005, 0x0,
+0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094,
+0x3c020001, 0x8c424f70, 0xac620000, 0x3c030001, 0x8c635094, 0x3c020001,
+0x8c424f70, 0xac620004, 0x3e00008, 0xaf430250, 0x3c030001, 0x8c635094,
+0x3c020001, 0x8c424f70, 0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010,
+0x808021, 0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821,
+0xafbf0028, 0xafb3001c, 0xafb20018, 0xac620000, 0x3c050001, 0x8ca55094,
+0x3c020001, 0x8c424f70, 0xc09021, 0xe09821, 0x10800006, 0xaca20004,
+0x24a50008, 0xc002490, 0x24060018, 0x800244e, 0x0, 0x24a40008,
+0xc002488, 0x24050018, 0x3c020001, 0x8c425094, 0x3c050001, 0x24a550c0,
+0x2442ffe0, 0x3c010001, 0xac225094, 0x45102b, 0x10400005, 0x0,
+0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094,
+0x8e020000, 0xac620000, 0x3c030001, 0x8c635094, 0x8e020004, 0xac620004,
+0xac710008, 0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225094, 0x45102b,
+0xac720010, 0xac730014, 0xac740018, 0xac75001c, 0x10400005, 0xac64000c,
+0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094,
+0x3c020001, 0x8c424f70, 0xac620000, 0x3c030001, 0x8c635094, 0x3c020001,
+0x8c424f70, 0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030,
+0x10a00005, 0x0, 0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004,
+0x3e00008, 0x0, 0x10c00007, 0x0, 0x8c820000, 0x24840004,
+0x24c6fffc, 0xaca20000, 0x14c0fffb, 0x24a50004, 0x3e00008, 0x0,
+0x10c00007, 0x0, 0x8ca20000, 0x24a50004, 0x24c6fffc, 0xac820000,
+0x14c0fffb, 0x24840004, 0x3e00008, 0x0, 0x3e00008, 0x0,
+0x27bdffd8, 0xafbf0020, 0x8ee304d4, 0x8ee204d0, 0x10620436, 0x0,
+0x8ee204d4, 0x8ee304ec, 0x21100, 0x626021, 0x95870008, 0x8d8a0000,
+0x8d8b0004, 0x958d000a, 0x8ee2724c, 0x8ee3725c, 0x30e4ffff, 0x441021,
+0x62182b, 0x10600015, 0x31a20004, 0x8f8200d8, 0x8ee37248, 0x431023,
+0xaee2725c, 0x8ee2725c, 0x1c400003, 0x3c030001, 0x431021, 0xaee2725c,
+0x8ee2724c, 0x8ee3725c, 0x441021, 0x62182b, 0x10600006, 0x31a20004,
+0x8ee201b4, 0x24420001, 0xaee201b4, 0x80028e1, 0x8ee201b4, 0x10400240,
+0x31a20200, 0x1040014d, 0x4821, 0x96e2045a, 0x30420010, 0x10400149,
+0x0, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001,
+0x27652800, 0x8f820108, 0x10a20004, 0x0, 0x8f820104, 0x14a20006,
+0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x800252c, 0x8ee201a4,
+0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 0xa482000e, 0xac860018,
+0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 0xac820010, 0xaf850100,
+0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28,
+0x2e22021, 0x8c820000, 0x1446001f, 0x0, 0x8ee34e18, 0x8ee24e1c,
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c,
+0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001,
+0x10a20005, 0x0, 0x8002516, 0x0, 0x14a00005, 0x0,
+0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011,
+0x50400013, 0xac800000, 0x800252c, 0x0, 0x8ee24e18, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18,
+0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000,
+0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, 0x8ee27254,
+0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be,
+0x34a5f114, 0x8ee27254, 0x34843800, 0x3641821, 0x24420010, 0x43102b,
+0x14400073, 0x0, 0x8ee27254, 0x24480010, 0x3641021, 0x102102b,
+0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000, 0x24a60020,
+0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 0x0,
+0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001,
+0xaee201a4, 0x80025a0, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000,
+0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018,
+0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010,
+0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0,
+0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0,
+0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
+0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0,
+0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x800258a, 0x0,
+0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80025a0, 0x0,
+0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18,
+0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021,
+0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc,
+0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014,
+0x8ee604d4, 0x80028be, 0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e,
+0x800261d, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b,
+0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 0x0, 0x8f820104,
+0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4,
+0x800260d, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004,
+0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018, 0x24630010,
+0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025,
+0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18,
+0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f,
+0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007,
+0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x80025f7,
+0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108,
+0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800260d,
+0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021,
+0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28,
+0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a,
+0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004,
+0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f015, 0x8ee37254, 0xa462000c,
+0x8ee37254, 0x9582000e, 0xa462000e, 0x8002681, 0x24e70004, 0x8f840100,
0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108,
-0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x80024cd,
-0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 0xa482000e,
-0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 0xac820010,
-0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0,
-0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 0x0, 0x8ee34e18,
+0x10a20004, 0x0, 0x8f820104, 0x14a20007, 0x24020006, 0x8ee201a4,
+0x4821, 0x24420001, 0xaee201a4, 0x8002677, 0x8ee201a4, 0xac8a0000,
+0xac8b0004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 0x8ee204d4,
+0xac82001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xac820010, 0xaf850100,
+0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28,
+0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18,
0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c,
-0x24420001, 0x10a20005, 0x0, 0x80024b7, 0x0, 0x14a00005,
+0x24420001, 0x10a20005, 0x0, 0x8002661, 0x0, 0x14a00005,
0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004,
-0x2c420011, 0x50400013, 0xac800000, 0x80024cd, 0x0, 0x8ee24e18,
+0x2c420011, 0x50400013, 0xac800000, 0x8002677, 0x0, 0x8ee24e18,
0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001,
0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005,
-0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010,
-0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4,
-0x800284a, 0x34a5f114, 0x8ee27254, 0x34843800, 0x3641821, 0x24420010,
-0x43102b, 0x14400070, 0x0, 0x8ee27254, 0x24480010, 0x3641021,
-0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000,
-0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x14c20007,
-0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 0x800253e,
-0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004, 0x24e2fff4,
-0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, 0x8ee204d4, 0xaca2001c,
-0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc,
-0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021,
-0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c,
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c,
-0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001,
-0x10a20005, 0x0, 0x8002528, 0x0, 0x14a00005, 0x0,
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x800253e, 0x0, 0x8ee24e18, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18,
-0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000,
-0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27254,
-0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a,
-0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, 0x80025b8, 0xa5020002,
-0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800,
-0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001,
-0xaee201a4, 0x80025a8, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000,
-0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018,
-0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002,
+0xac820000, 0x24020001, 0xac820004, 0x15200009, 0x3c050004, 0xafab0010,
+0x8ee27254, 0x3c040001, 0x24844af0, 0xafa20014, 0x8ee604d4, 0x80028be,
+0x34a5f004, 0x8ee2724c, 0x30e7ffff, 0x471021, 0xaee2724c, 0x8ee204d4,
+0x8ee304ec, 0x8ee47248, 0x21100, 0x431021, 0xac44000c, 0x8ee27248,
+0xafa20018, 0x8ee3724c, 0xafa3001c, 0x8ee2724c, 0x2c42003c, 0x10400004,
+0x24620001, 0x2403fffe, 0x431024, 0xafa2001c, 0x8ee27254, 0x3c060001,
+0x34c63800, 0x8ee3724c, 0x2405fff8, 0x471021, 0x24420007, 0x451024,
+0x24630007, 0xaee27248, 0x8ee2725c, 0x8ee47248, 0x651824, 0x431023,
+0xaee2725c, 0x3661021, 0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248,
+0x431021, 0xaee27248, 0x8ee27248, 0xaee27254, 0x8f8200f0, 0x24470008,
+0x27621800, 0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007,
+0x0, 0x8ee201b0, 0x4821, 0x24420001, 0xaee201b0, 0x80026c4,
+0x8ee201b0, 0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000,
+0xac440004, 0xaf8700f0, 0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010,
+0x8f8200f4, 0x3c040001, 0x24844afc, 0xafa20014, 0x8fa60018, 0x8fa7001c,
+0x3c050004, 0xc002403, 0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088,
+0x8ee20088, 0x80028d3, 0xaee0724c, 0x30430003, 0x24020002, 0x10620016,
+0x28620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x8002703,
+0x0, 0x24020003, 0x10620017, 0x0, 0x8002703, 0x0,
+0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 0xaee200e8,
+0xaee300ec, 0x8ee200e8, 0x8002703, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4,
+0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 0xaee300f4, 0x8ee200f0,
+0x8002703, 0x8ee300f4, 0x8ee200f8, 0x8ee300fc, 0x24630001, 0x2c640001,
+0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, 0x8ee300fc, 0x8ee2724c,
+0x8ee400e0, 0x8ee500e4, 0x401821, 0x1021, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xaee400e0, 0xaee500e4, 0x80028d3, 0xaee0724c,
+0x30e2ffff, 0x104001c1, 0x31a20200, 0x1040014d, 0x4821, 0x96e2045a,
+0x30420010, 0x10400149, 0x0, 0x8f840100, 0x27623000, 0x24850020,
+0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a20004, 0x0,
+0x8f820104, 0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4,
+0x800276e, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005,
+0xa482000e, 0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8,
+0xac820010, 0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18,
+0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 0x0,
+0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
+0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0,
+0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x8002758, 0x0,
+0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800276e, 0x0,
+0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18,
+0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021,
+0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001,
+0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014,
+0x8ee604d4, 0x80028be, 0x34a5f014, 0x8ee27254, 0x34843800, 0x3641821,
+0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27254, 0x24480010,
+0x3641021, 0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100,
+0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108,
+0x10c20004, 0x0, 0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4,
+0x4821, 0x24420001, 0xaee201a4, 0x80027e2, 0x8ee201a4, 0x2c64000c,
+0x1441021, 0xaca20000, 0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006,
+0xaca80008, 0xaca20018, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002,
0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001,
0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005,
0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040,
0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001,
0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0,
-0x8002592, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020,
+0x80027cc, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020,
0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x80025a8, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003,
+0x80027e2, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003,
0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0,
0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004,
-0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0,
-0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f015, 0x8ee37254,
-0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 0x8002619, 0x24e70004,
-0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800,
-0x8f820108, 0x14a20007, 0x24020006, 0x8ee201a4, 0x4821, 0x24420001,
-0xaee201a4, 0x800260f, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254,
-0xa487000e, 0xac820018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8,
-0x3c030002, 0x431025, 0xac820010, 0xaf850100, 0x92e204dc, 0x14400037,
+0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0,
+0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f015, 0x34028100,
+0xa5020000, 0x9582000e, 0x800285f, 0xa5020002, 0x8f850100, 0x27623000,
+0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004,
+0x0, 0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821,
+0x24420001, 0xaee201a4, 0x800284f, 0x8ee201a4, 0x2c64000c, 0x1441021,
+0xaca20000, 0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006,
+0xaca20018, 0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8,
+0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037,
0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000,
0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b,
0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18,
0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005,
-0x0, 0x80025f9, 0x0, 0x14a00005, 0x0, 0x8f820108,
+0x0, 0x8002839, 0x0, 0x14a00005, 0x0, 0x8f820108,
0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x800260f, 0x0, 0x8ee24e18, 0x24030040, 0x24420001,
+0xac800000, 0x800284f, 0x0, 0x8ee24e18, 0x24030040, 0x24420001,
0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18,
0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x15200009, 0x3c050004, 0xafab0010, 0x8ee27254, 0x3c040001,
-0x248448e0, 0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f004, 0x8ee2724c,
-0x30e7ffff, 0x471021, 0xaee2724c, 0x8ee204d4, 0x8ee304ec, 0x8ee47248,
-0x21100, 0x431021, 0xac44000c, 0x8ee27248, 0xafa20018, 0x8ee3724c,
-0xafa3001c, 0x8ee2724c, 0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe,
-0x431024, 0xafa2001c, 0x8ee27254, 0x3c060001, 0x34c63800, 0x8ee3724c,
-0x2405fff8, 0x471021, 0x24420007, 0x451024, 0x24630007, 0xaee27248,
-0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 0x3661021,
-0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 0xaee27248,
-0x8ee27248, 0xaee27254, 0x8f8200f0, 0x24470008, 0x27621800, 0xe2102b,
-0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 0x0, 0x8ee201b0,
-0x4821, 0x24420001, 0xaee201b0, 0x800265c, 0x8ee201b0, 0x8f8200f0,
-0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, 0xaf8700f0,
-0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4, 0x3c040001,
-0x248448ec, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050004, 0xc0023a7,
-0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088, 0x800285f,
-0xaee0724c, 0x30430003, 0x24020002, 0x10620016, 0x28620003, 0x10400005,
-0x24020001, 0x10620008, 0x0, 0x800269b, 0x0, 0x24020003,
-0x10620017, 0x0, 0x800269b, 0x0, 0x8ee200e8, 0x8ee300ec,
-0x24630001, 0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8,
-0x800269b, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001,
-0x441021, 0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x800269b, 0x8ee300f4,
-0x8ee200f8, 0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8,
-0xaee300fc, 0x8ee200f8, 0x8ee300fc, 0x8ee2724c, 0x8ee400e0, 0x8ee500e4,
-0x401821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xaee400e0, 0xaee500e4, 0x800285f, 0xaee0724c, 0x30e2ffff, 0x104001b5,
-0x31a20200, 0x10400144, 0x4821, 0x96e2045a, 0x30420010, 0x10400140,
-0x0, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001,
-0x27652800, 0x8f820108, 0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001,
-0xaee201a4, 0x8002703, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254,
-0x24060005, 0xa482000e, 0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c,
-0x8ee204b8, 0xac820010, 0xaf850100, 0x92e204dc, 0x14400036, 0x24090001,
-0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f,
-0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007,
-0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x80026ed,
-0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108,
-0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002703,
-0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28,
-0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a,
-0x3c040001, 0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004,
-0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f014, 0x8ee27254, 0x34843800,
-0x3641821, 0x24420010, 0x43102b, 0x14400070, 0x0, 0x8ee27254,
-0x24480010, 0x3641021, 0x102102b, 0x14400002, 0x3c02ffff, 0x1024021,
-0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800,
-0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001,
-0xaee201a4, 0x8002774, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000,
-0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018,
-0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010,
-0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0,
-0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0,
-0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0,
-0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x800275e, 0x0,
-0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002774, 0x0,
-0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18,
-0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021,
-0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc,
-0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014,
-0x8ee604d4, 0x800284a, 0x34a5f015, 0x34028100, 0xa5020000, 0x9582000e,
-0x80027ee, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b,
-0x50400001, 0x27662800, 0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4,
-0x4821, 0x24420001, 0xaee201a4, 0x80027de, 0x8ee201a4, 0x2c64000c,
-0x1441021, 0xaca20000, 0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e,
-0x24020006, 0xaca20018, 0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c,
-0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc,
-0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021,
-0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c,
+0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001,
+0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f016,
+0x8ee37254, 0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 0x80028c2,
+0x24e70004, 0x8f830100, 0x27623000, 0x24640020, 0x82102b, 0x50400001,
+0x27642800, 0x8f820108, 0x10820004, 0x0, 0x8f820104, 0x14820007,
+0x24050005, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 0x80028b6,
+0x8ee201a4, 0xac6a0000, 0xac6b0004, 0x8ee27254, 0xa467000e, 0xac650018,
+0xac620008, 0x8ee204d4, 0xac62001c, 0x8ee204b8, 0xac620010, 0xaf840100,
+0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28,
+0x2e22021, 0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c,
0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c,
0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001,
-0x10a20005, 0x0, 0x80027c8, 0x0, 0x14a00005, 0x0,
+0x10a20005, 0x0, 0x80028a0, 0x0, 0x14a00005, 0x0,
0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011,
-0x50400013, 0xac800000, 0x80027de, 0x0, 0x8ee24e18, 0x24030040,
+0x50400013, 0xac800000, 0x80028b6, 0x0, 0x8ee24e18, 0x24030040,
0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18,
0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000,
-0x24020001, 0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254,
-0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a,
-0x34a5f016, 0x8ee37254, 0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e,
-0x800284e, 0x24e70004, 0x8f830100, 0x27623000, 0x24640020, 0x82102b,
-0x50400001, 0x27642800, 0x8f820108, 0x14820007, 0x24050005, 0x8ee201a4,
-0x4821, 0x24420001, 0xaee201a4, 0x8002842, 0x8ee201a4, 0xac6a0000,
-0xac6b0004, 0x8ee27254, 0xa467000e, 0xac650018, 0xac620008, 0x8ee204d4,
-0xac62001c, 0x8ee204b8, 0xac620010, 0xaf840100, 0x92e204dc, 0x14400036,
-0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000,
+0x24020001, 0xac820004, 0x1520000b, 0x3c050004, 0x3c040001, 0x24844b08,
+0xafab0010, 0xafa00014, 0x8ee604d4, 0x34a5f017, 0xc002403, 0x30e7ffff,
+0x80028e1, 0x0, 0x8ee27254, 0x3c050001, 0x30e4ffff, 0x441021,
+0xaee27254, 0x8ee2724c, 0x8ee37254, 0x34a53800, 0x441021, 0xaee2724c,
+0x3651021, 0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021,
+0xaee27254, 0x8ee304d4, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824,
+0xaee304d4, 0x8ee304d4, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060,
+0x2403fff7, 0x431024, 0xaf820060, 0x8fbf0020, 0x3e00008, 0x27bd0028,
+0x27bdffe0, 0xafbf0018, 0x8ee304d8, 0x8ee204d0, 0x10620189, 0x0,
+0x8ee204d8, 0x8ee304ec, 0x21100, 0x621821, 0x94670008, 0x92e204dd,
+0x8c680000, 0x8c690004, 0x10400023, 0x946a000a, 0x8ee204b8, 0x34460400,
+0x31420200, 0x1040001f, 0x0, 0x96e2045a, 0x30420010, 0x1040001b,
+0x3c028000, 0x3c010001, 0x370821, 0xac2283c8, 0x8ee27254, 0x9464000e,
+0x3c050001, 0x34a53800, 0x24420004, 0xaee27254, 0x8ee37254, 0x42400,
+0x3651021, 0x3c010001, 0x370821, 0xac2483cc, 0x62182b, 0x14600005,
+0x24e70004, 0x8ee27254, 0x3c03ffff, 0x431021, 0xaee27254, 0x8ee27254,
+0x8002917, 0xaee27248, 0x8ee604b8, 0x8ee2725c, 0x30e4ffff, 0x44102a,
+0x10400015, 0x0, 0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c,
+0x8ee2725c, 0x1c400007, 0x44102a, 0x8ee2725c, 0x3c030001, 0x431021,
+0xaee2725c, 0x8ee2725c, 0x44102a, 0x10400006, 0x0, 0x8ee201b4,
+0x24420001, 0xaee201b4, 0x8002a72, 0x8ee201b4, 0x3c020001, 0x571021,
+0x8c4283c8, 0x54400001, 0x24e7fffc, 0x31420004, 0x104000b9, 0x30e2ffff,
+0x3c020001, 0x571021, 0x8c4283c8, 0x1040002f, 0x5021, 0x8f840100,
+0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108,
+0x10a20032, 0x0, 0x8f820104, 0x10a2002f, 0x24020015, 0xac880000,
+0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 0x8ee204d8,
+0x3c030001, 0x771821, 0x8c6383cc, 0xac860010, 0x431025, 0xac82001c,
+0xaf850100, 0x92e204dc, 0x14400066, 0x240a0001, 0x8ee24e18, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18,
+0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020015, 0xac620000,
+0x24020001, 0x80029bf, 0xac620004, 0x8f840100, 0x27623000, 0x24850020,
+0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a20004, 0x0,
+0x8f820104, 0x14a20006, 0x24020006, 0x8ee201a4, 0x24420001, 0xaee201a4,
+0x80029bf, 0x8ee201a4, 0xac880000, 0xac890004, 0x8ee37254, 0xa487000e,
+0xac820018, 0xac830008, 0x8ee204d8, 0xac860010, 0xac82001c, 0xaf850100,
+0x92e204dc, 0x14400037, 0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28,
+0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18,
+0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
+0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c,
+0x24420001, 0x10a20005, 0x0, 0x80029a9, 0x0, 0x14a00005,
+0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004,
+0x2c420011, 0x50400013, 0xac800000, 0x80029bf, 0x0, 0x8ee24e18,
+0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001,
+0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005,
+0xac820000, 0x24020001, 0xac820004, 0x1540000a, 0x24020001, 0xafa90010,
+0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4,
+0x8002a4f, 0x34a5f204, 0xa2e204dd, 0x8ee204d8, 0x8ee304ec, 0x8ee47248,
+0x3c060001, 0x34c63800, 0x3c010001, 0x370821, 0xac2083c8, 0x3c010001,
+0x370821, 0xac2083cc, 0x21100, 0x431021, 0xac44000c, 0x8ee27254,
+0x2405fff8, 0x30e3ffff, 0x431021, 0x24420007, 0x451024, 0x24630007,
+0xaee27248, 0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 0xaee2725c,
+0x3661021, 0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021,
+0xaee27248, 0x8ee27248, 0x8002a64, 0xaee27254, 0x10400073, 0x0,
+0x8f830100, 0x27623000, 0x24640020, 0x82102b, 0x14400002, 0x5021,
+0x27642800, 0x8f820108, 0x10820004, 0x0, 0x8f820104, 0x14820006,
+0x24050005, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x8002a46, 0x8ee201a4,
+0xac680000, 0xac690004, 0x8ee27254, 0xa467000e, 0xac650018, 0xac620008,
+0x8ee204d8, 0xac660010, 0xac62001c, 0xaf840100, 0x92e204dc, 0x14400036,
+0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000,
0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040,
0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001,
0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0,
-0x800282c, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020,
+0x8002a30, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020,
0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x8002842, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003,
+0x8002a46, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003,
0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0,
0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004,
-0x1520000b, 0x3c050004, 0x3c040001, 0x248448f8, 0xafab0010, 0xafa00014,
-0x8ee604d4, 0x34a5f017, 0xc0023a7, 0x30e7ffff, 0x800286d, 0x0,
-0x8ee27254, 0x3c050001, 0x30e4ffff, 0x441021, 0xaee27254, 0x8ee2724c,
-0x8ee37254, 0x34a53800, 0x441021, 0xaee2724c, 0x3651021, 0x62182b,
-0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 0xaee27254, 0x8ee304d4,
-0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d4, 0x8ee304d4,
-0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 0x2403fff7, 0x431024,
-0xaf820060, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x27bdffe0, 0xafbf0018,
-0x8ee304d8, 0x8ee204d0, 0x10620180, 0x0, 0x8ee204d8, 0x8ee304ec,
-0x21100, 0x621821, 0x94670008, 0x92e204dd, 0x8c680000, 0x8c690004,
-0x10400023, 0x946a000a, 0x8ee204b8, 0x34460400, 0x31420200, 0x1040001f,
-0x0, 0x96e2045a, 0x30420010, 0x1040001b, 0x3c028000, 0x3c010001,
-0x370821, 0xac2283c8, 0x8ee27254, 0x9464000e, 0x3c050001, 0x34a53800,
-0x24420004, 0xaee27254, 0x8ee37254, 0x42400, 0x3651021, 0x3c010001,
-0x370821, 0xac2483cc, 0x62182b, 0x14600005, 0x24e70004, 0x8ee27254,
-0x3c03ffff, 0x431021, 0xaee27254, 0x8ee27254, 0x80028a3, 0xaee27248,
-0x8ee604b8, 0x8ee2725c, 0x30e4ffff, 0x44102a, 0x10400015, 0x0,
-0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 0x8ee2725c, 0x1c400007,
-0x44102a, 0x8ee2725c, 0x3c030001, 0x431021, 0xaee2725c, 0x8ee2725c,
-0x44102a, 0x10400006, 0x0, 0x8ee201b4, 0x24420001, 0xaee201b4,
-0x80029f5, 0x8ee201b4, 0x3c020001, 0x571021, 0x8c4283c8, 0x54400001,
-0x24e7fffc, 0x31420004, 0x104000b3, 0x30e2ffff, 0x3c020001, 0x571021,
-0x8c4283c8, 0x1040002c, 0x5021, 0x8f840100, 0x27623000, 0x24850020,
-0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a2002c, 0x24020015,
-0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008,
-0x8ee204d8, 0x3c030001, 0x771821, 0x8c6383cc, 0xac860010, 0x431025,
-0xac82001c, 0xaf850100, 0x92e204dc, 0x14400063, 0x240a0001, 0x8ee24e18,
-0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001,
-0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020015,
-0xac620000, 0x24020001, 0x8002945, 0xac620004, 0x8f840100, 0x27623000,
-0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x14a20006,
-0x24020006, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x8002945, 0x8ee201a4,
-0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008,
-0x8ee204d8, 0xac860010, 0xac82001c, 0xaf850100, 0x92e204dc, 0x14400037,
-0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000,
-0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18,
-0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005,
-0x0, 0x800292f, 0x0, 0x14a00005, 0x0, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x8002945, 0x0, 0x8ee24e18, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18,
-0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x1540000a, 0x24020001, 0xafa90010, 0x8ee27254, 0x3c040001,
-0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80029d2, 0x34a5f204,
-0xa2e204dd, 0x8ee204d8, 0x8ee304ec, 0x8ee47248, 0x3c060001, 0x34c63800,
-0x3c010001, 0x370821, 0xac2083c8, 0x3c010001, 0x370821, 0xac2083cc,
-0x21100, 0x431021, 0xac44000c, 0x8ee27254, 0x2405fff8, 0x30e3ffff,
-0x431021, 0x24420007, 0x451024, 0x24630007, 0xaee27248, 0x8ee2725c,
-0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 0x3661021, 0x82202b,
-0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 0xaee27248, 0x8ee27248,
-0x80029e7, 0xaee27254, 0x10400070, 0x0, 0x8f830100, 0x27623000,
-0x24640020, 0x82102b, 0x14400002, 0x5021, 0x27642800, 0x8f820108,
-0x14820006, 0x24050005, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x80029c9,
-0x8ee201a4, 0xac680000, 0xac690004, 0x8ee27254, 0xa467000e, 0xac650018,
-0xac620008, 0x8ee204d8, 0xac660010, 0xac62001c, 0xaf840100, 0x92e204dc,
-0x14400036, 0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021,
-0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b,
-0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18,
-0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005,
-0x0, 0x80029b3, 0x0, 0x14a00005, 0x0, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x80029c9, 0x0, 0x8ee24e18, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18,
-0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001,
-0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001, 0x248448f8, 0x3c050004,
-0xafa90010, 0xafa00014, 0x8ee604d4, 0x34a5f237, 0xc0023a7, 0x30e7ffff,
-0x80029f5, 0x0, 0x8ee27254, 0x451021, 0xaee27254, 0x8ee2725c,
-0x8ee37254, 0x3c040001, 0x34843800, 0xa2e004dd, 0x451023, 0xaee2725c,
-0x3641021, 0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021,
-0xaee27254, 0x8ee304d8, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824,
-0xaee304d8, 0x8ee304d8, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060,
-0x2403fff7, 0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820100, 0x8ee34e1c, 0x8f820104,
-0x8f850108, 0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ee24e1c,
-0x24420001, 0xaee24e1c, 0x8ee24e1c, 0x8ee34e1c, 0x210c0, 0x24424e28,
-0x2e22021, 0x8ee24e18, 0x8c870004, 0x14620007, 0xa03021, 0x8f820108,
-0x24420020, 0xaf820108, 0x8f820108, 0x8002a25, 0xac800000, 0x8ee24e1c,
-0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e1c, 0x24420001,
-0x210c0, 0x24424e28, 0x2e22021, 0x8c820004, 0x8f830108, 0x21140,
-0x621821, 0xaf830108, 0xac800000, 0x8cc30018, 0x2c620002, 0x144000b7,
-0x2c620004, 0x5440008a, 0x24030040, 0x2c620007, 0x104000b2, 0x2c620005,
-0x144000b0, 0x0, 0x8ee204e0, 0x471021, 0xaee204e0, 0x8ee204e0,
-0x8f43023c, 0x43102b, 0x144000b2, 0x0, 0x8ee304d4, 0x8ee204e8,
-0x506200ae, 0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
-0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0,
-0x8021, 0x24420001, 0xaee201a0, 0x8002a93, 0x8ee201a0, 0x8ee204d4,
-0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008,
-0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4,
-0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f,
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007,
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8002a7d,
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002a93,
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b,
-0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, 0xafa00014, 0xafa20010,
-0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f006, 0x16000003,
-0x24020001, 0x8002ae9, 0xa2e204e4, 0x8ee2016c, 0x24420001, 0xaee2016c,
-0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee204e8, 0x8f42023c,
-0x5040003c, 0xaee07264, 0x8ee20180, 0x24420001, 0xaee20180, 0x8ee20180,
-0x8002ae9, 0xaee07264, 0x8ee204f4, 0x24420001, 0x50430003, 0x1021,
-0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 0x8cc30018, 0x21080,
-0x571021, 0x8c4404f8, 0x24020003, 0x1462000f, 0x0, 0x3c020001,
-0x571021, 0x904283a1, 0x10400014, 0x0, 0x8ee201c8, 0x8ee35230,
-0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 0x306300ff, 0x8002ad9,
-0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc,
-0x641821, 0x306301ff, 0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000,
-0x34420040, 0x8002ae9, 0xaee20000, 0x94c7000e, 0x8cc2001c, 0x3c040001,
-0x24844910, 0xafa60014, 0xafa20010, 0x8cc60018, 0x3c050008, 0xc0023a7,
-0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x27bdff98,
-0xafbf0060, 0xafbe005c, 0xafb60058, 0xafb50054, 0xafb40050, 0xafb3004c,
-0xafb20048, 0xafb10044, 0xafb00040, 0x8f830108, 0x8f820104, 0xafa00024,
-0x106203d9, 0xafa0002c, 0x3c1e0001, 0x37de3800, 0x3c0bffff, 0x8f930108,
-0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, 0x104003c1, 0x31080,
-0x3c010001, 0x220821, 0x8c224920, 0x400008, 0x0, 0x9663000e,
-0x8ee2724c, 0x8ee404e0, 0x431021, 0xaee2724c, 0x8e63001c, 0x96e20458,
-0x24840001, 0xaee404e0, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d4,
-0x8f42023c, 0x82202b, 0x148003ab, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007,
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002b73,
+0x1540000c, 0x30e5ffff, 0x3c040001, 0x24844b08, 0x3c050004, 0xafa90010,
+0xafa00014, 0x8ee604d4, 0x34a5f237, 0xc002403, 0x30e7ffff, 0x8002a72,
+0x0, 0x8ee27254, 0x451021, 0xaee27254, 0x8ee2725c, 0x8ee37254,
+0x3c040001, 0x34843800, 0xa2e004dd, 0x451023, 0xaee2725c, 0x3641021,
+0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 0xaee27254,
+0x8ee304d8, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d8,
+0x8ee304d8, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 0x2403fff7,
+0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0,
+0xafbf001c, 0xafb00018, 0x8f820100, 0x8ee34e1c, 0x8f820104, 0x8f850108,
+0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ee24e1c, 0x24420001,
+0xaee24e1c, 0x8ee24e1c, 0x8ee34e1c, 0x210c0, 0x24424e28, 0x2e22021,
+0x8ee24e18, 0x8c870004, 0x14620007, 0xa03021, 0x8f820108, 0x24420020,
+0xaf820108, 0x8f820108, 0x8002aa2, 0xac800000, 0x8ee24e1c, 0x24030040,
+0x24420001, 0x50430003, 0x1021, 0x8ee24e1c, 0x24420001, 0x210c0,
+0x24424e28, 0x2e22021, 0x8c820004, 0x8f830108, 0x21140, 0x621821,
+0xaf830108, 0xac800000, 0x8cc30018, 0x2c620002, 0x144000ba, 0x2c620004,
+0x5440008d, 0x24030040, 0x2c620007, 0x104000b5, 0x2c620005, 0x144000b3,
+0x0, 0x8ee204e0, 0x471021, 0xaee204e0, 0x8ee204e0, 0x8f43023c,
+0x43102b, 0x144000b5, 0x0, 0x8ee304d4, 0x8ee204e8, 0x506200b1,
+0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001,
+0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007,
+0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002b13,
0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c,
0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000,
0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037,
0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8002b5d, 0x0, 0x14600005, 0x0, 0x8f820128,
+0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20,
+0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005,
+0x0, 0x8002afd, 0x0, 0x14a00005, 0x0, 0x8f820128,
0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x8002b73, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001,
-0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000,
-0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904,
-0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006,
-0xc0023a7, 0xafab0038, 0x8fab0038, 0x12000307, 0x240c0001, 0x8002e8b,
-0x0, 0x966c001c, 0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024,
-0xae62001c, 0x8e75001c, 0x8ee204ec, 0x8ee404ec, 0x151900, 0x621021,
-0x8c52000c, 0x92e27b88, 0x641821, 0x9476000a, 0x14400003, 0x32c20002,
-0xaef27b94, 0xaef57b8c, 0x1040004b, 0x8021, 0x96e2045a, 0x30420002,
-0x10400047, 0x0, 0x8e63001c, 0x8ee204ec, 0x32100, 0x821021,
-0x8c42000c, 0x37e1821, 0x24420022, 0x43102b, 0x1440000a, 0x24050014,
-0x8ee204ec, 0x821021, 0x8c44000c, 0xafab0038, 0xc002edf, 0x2484000e,
-0x8fab0038, 0x8002bc7, 0x3050ffff, 0x8ee204ec, 0x821021, 0x8c42000c,
-0x9450000e, 0x94430010, 0x94440012, 0x94450014, 0x2038021, 0x2048021,
-0x2058021, 0x94430016, 0x94440018, 0x9445001a, 0x2038021, 0x2048021,
-0x2058021, 0x9443001c, 0x9444001e, 0x94420020, 0x2038021, 0x2048021,
-0x2028021, 0x101c02, 0x3202ffff, 0x628021, 0x8e63001c, 0x8ee204ec,
-0x102402, 0x32900, 0xa21021, 0x8c43000c, 0x3202ffff, 0x828021,
-0x37e1021, 0x24630018, 0x62182b, 0x14600009, 0x0, 0x8ee204ec,
-0xa21021, 0x8c43000c, 0x101027, 0x3c01ffff, 0x230821, 0x8002be4,
-0xa4220018, 0x8ee204ec, 0xa21021, 0x8c43000c, 0x101027, 0xa4620018,
-0x96e2045a, 0x8821, 0x30420008, 0x14400063, 0xa021, 0x8e63001c,
-0x8ee204ec, 0x33100, 0xc21021, 0x8c42000c, 0x37e1821, 0x24420022,
-0x43102b, 0x14400035, 0x0, 0x8ee204ec, 0xc21021, 0x8c42000c,
-0x24470010, 0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x8ee204ec,
-0x94f10000, 0xc21021, 0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b,
-0x14400002, 0x2634ffec, 0xeb3821, 0x8ee204ec, 0x90e30001, 0xc21021,
-0x8c42000c, 0x2447001a, 0x37e1021, 0xe2102b, 0x14400002, 0x2838821,
+0xac800000, 0x8002b13, 0x0, 0x8ee24e20, 0x24030040, 0x24420001,
+0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001,
+0xac820004, 0x5600000b, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844b14,
+0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403,
+0x34a5f006, 0x16000003, 0x24020001, 0x8002b69, 0xa2e204e4, 0x8ee2016c,
+0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0,
+0xaee204e8, 0x8f42023c, 0x5040003c, 0xaee07264, 0x8ee20180, 0x24420001,
+0xaee20180, 0x8ee20180, 0x8002b69, 0xaee07264, 0x8ee204f4, 0x24420001,
+0x50430003, 0x1021, 0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4,
+0x8cc30018, 0x21080, 0x571021, 0x8c4404f8, 0x24020003, 0x1462000f,
+0x0, 0x3c020001, 0x571021, 0x904283a1, 0x10400014, 0x0,
+0x8ee201c8, 0x8ee35230, 0x441021, 0xaee201c8, 0x8ee201cc, 0x641821,
+0x306300ff, 0x8002b59, 0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021,
+0xaee201c4, 0x8ee201cc, 0x641821, 0x306301ff, 0xaee30e00, 0x441021,
+0xaee201cc, 0x8ee20000, 0x34420040, 0x8002b69, 0xaee20000, 0x94c7000e,
+0x8cc2001c, 0x3c040001, 0x24844b20, 0xafa60014, 0xafa20010, 0x8cc60018,
+0x3c050008, 0xc002403, 0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008,
+0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058, 0xafb50054,
+0xafb40050, 0xafb3004c, 0xafb20048, 0xafb10044, 0xafb00040, 0x8f830108,
+0x8f820104, 0xafa00024, 0x106203df, 0xafa0002c, 0x3c1e0001, 0x37de3800,
+0x3c0bffff, 0x8f930108, 0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014,
+0x104003c7, 0x31080, 0x3c010001, 0x220821, 0x8c224b30, 0x400008,
+0x0, 0x9663000e, 0x8ee2724c, 0x8ee404e0, 0x431021, 0xaee2724c,
+0x8e63001c, 0x96e20458, 0x24840001, 0xaee404e0, 0x24630001, 0x2442ffff,
+0x621824, 0xaee304d4, 0x8f42023c, 0x82202b, 0x148003b1, 0x0,
+0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000,
+0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0,
+0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002bf6, 0x8ee201a0,
+0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008,
+0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004,
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012,
+0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x240c0040,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
+0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
+0x8002be0, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
+0x8002bf6, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, 0x504c0003,
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004,
+0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844b14, 0xafa00014,
+0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403,
+0xafab0038, 0x8fab0038, 0x1200030a, 0x240c0001, 0x8002f11, 0x0,
+0x966c001c, 0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024, 0xae62001c,
+0x8e75001c, 0x8ee204ec, 0x8ee404ec, 0x151900, 0x621021, 0x8c52000c,
+0x92e27b88, 0x641821, 0x9476000a, 0x14400003, 0x32c20002, 0xaef27b94,
+0xaef57b8c, 0x1040004b, 0x8021, 0x96e2045a, 0x30420002, 0x10400047,
+0x0, 0x8e63001c, 0x8ee204ec, 0x32100, 0x821021, 0x8c42000c,
+0x37e1821, 0x24420022, 0x43102b, 0x1440000a, 0x24050014, 0x8ee204ec,
+0x821021, 0x8c44000c, 0xafab0038, 0xc002f65, 0x2484000e, 0x8fab0038,
+0x8002c4a, 0x3050ffff, 0x8ee204ec, 0x821021, 0x8c42000c, 0x9450000e,
+0x94430010, 0x94440012, 0x94450014, 0x2038021, 0x2048021, 0x2058021,
+0x94430016, 0x94440018, 0x9445001a, 0x2038021, 0x2048021, 0x2058021,
+0x9443001c, 0x9444001e, 0x94420020, 0x2038021, 0x2048021, 0x2028021,
+0x101c02, 0x3202ffff, 0x628021, 0x8e63001c, 0x8ee204ec, 0x102402,
+0x32900, 0xa21021, 0x8c43000c, 0x3202ffff, 0x828021, 0x37e1021,
+0x24630018, 0x62182b, 0x14600009, 0x0, 0x8ee204ec, 0xa21021,
+0x8c43000c, 0x101027, 0x3c01ffff, 0x230821, 0x8002c67, 0xa4220018,
+0x8ee204ec, 0xa21021, 0x8c43000c, 0x101027, 0xa4620018, 0x96e2045a,
+0x8821, 0x30420008, 0x14400063, 0xa021, 0x8e63001c, 0x8ee204ec,
+0x33100, 0xc21021, 0x8c42000c, 0x37e1821, 0x24420022, 0x43102b,
+0x14400035, 0x0, 0x8ee204ec, 0xc21021, 0x8c42000c, 0x24470010,
+0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x8ee204ec, 0x94f10000,
+0xc21021, 0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b, 0x14400002,
+0x2634ffec, 0xeb3821, 0x8ee204ec, 0x90e30001, 0xc21021, 0x8c42000c,
+0x2447001a, 0x37e1021, 0xe2102b, 0x14400002, 0x2838821, 0xeb3821,
+0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 0xe2102b, 0x50400001,
0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 0xe2102b,
0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 0x37e1021,
-0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821,
-0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x8002c45,
-0x2228821, 0x8ee204ec, 0xc21021, 0x8c43000c, 0x8ee204ec, 0x94710010,
-0x8ee304ec, 0xc21021, 0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec,
-0x90840017, 0x8ee304ec, 0x9442001a, 0x2848821, 0xc31821, 0x8c65000c,
-0x8ee304ec, 0x2228821, 0x8ee204ec, 0xc31821, 0xc21021, 0x8c44000c,
-0x8c62000c, 0x94a3001c, 0x9484001e, 0x94420020, 0x2238821, 0x2248821,
-0x2228821, 0x111c02, 0x3222ffff, 0x628821, 0x111c02, 0x3222ffff,
-0x628821, 0x32c20001, 0x104000b2, 0x0, 0x96e2045a, 0x30420001,
-0x104000ae, 0x32c20080, 0x10400008, 0x0, 0x92e27b88, 0x14400005,
-0x0, 0x240c0001, 0xa2ec7b88, 0xaef57b8c, 0xaef27b94, 0x8ee304ec,
-0x151100, 0x431021, 0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b,
-0x14400008, 0xe02021, 0x2405000e, 0xc002edf, 0xafab0038, 0x3042ffff,
-0x8fab0038, 0x8002c7e, 0x2028021, 0x94e60000, 0x24e70002, 0x94e50000,
-0x24e70002, 0x94e30000, 0x24e70002, 0x94e20000, 0x24e70002, 0x94e40000,
-0x24e70002, 0x2068021, 0x2058021, 0x2038021, 0x2028021, 0x94e20000,
-0x94e30002, 0x2048021, 0x2028021, 0x2038021, 0x101c02, 0x3202ffff,
-0x628021, 0x101c02, 0x3202ffff, 0x8ee47b8c, 0x628021, 0x14950004,
-0x3205ffff, 0x96620016, 0x8002c8c, 0x512021, 0x96620016, 0x542021,
-0x41402, 0x3083ffff, 0x432021, 0x852023, 0x41402, 0x822021,
-0x3084ffff, 0x50800001, 0x3404ffff, 0x8ee27b94, 0x24430017, 0x37e1021,
-0x62102b, 0x50400001, 0x6b1821, 0x90630000, 0x24020011, 0x14620031,
-0x24020006, 0x8ee27b94, 0x37e1821, 0x24420028, 0x43102b, 0x14400018,
+0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x8002cc8, 0x2228821,
+0x8ee204ec, 0xc21021, 0x8c43000c, 0x8ee204ec, 0x94710010, 0x8ee304ec,
+0xc21021, 0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec, 0x90840017,
+0x8ee304ec, 0x9442001a, 0x2848821, 0xc31821, 0x8c65000c, 0x8ee304ec,
+0x2228821, 0x8ee204ec, 0xc31821, 0xc21021, 0x8c44000c, 0x8c62000c,
+0x94a3001c, 0x9484001e, 0x94420020, 0x2238821, 0x2248821, 0x2228821,
+0x111c02, 0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, 0x628821,
+0x32c20001, 0x104000b2, 0x0, 0x96e2045a, 0x30420001, 0x104000ae,
+0x32c20080, 0x10400008, 0x0, 0x92e27b88, 0x14400005, 0x0,
+0x240c0001, 0xa2ec7b88, 0xaef57b8c, 0xaef27b94, 0x8ee304ec, 0x151100,
+0x431021, 0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b, 0x14400008,
+0xe02021, 0x2405000e, 0xc002f65, 0xafab0038, 0x3042ffff, 0x8fab0038,
+0x8002d01, 0x2028021, 0x94e60000, 0x24e70002, 0x94e50000, 0x24e70002,
+0x94e30000, 0x24e70002, 0x94e20000, 0x24e70002, 0x94e40000, 0x24e70002,
+0x2068021, 0x2058021, 0x2038021, 0x2028021, 0x94e20000, 0x94e30002,
+0x2048021, 0x2028021, 0x2038021, 0x101c02, 0x3202ffff, 0x628021,
+0x101c02, 0x3202ffff, 0x8ee47b8c, 0x628021, 0x14950004, 0x3205ffff,
+0x96620016, 0x8002d0f, 0x512021, 0x96620016, 0x542021, 0x41402,
+0x3083ffff, 0x432021, 0x852023, 0x41402, 0x822021, 0x3084ffff,
+0x50800001, 0x3404ffff, 0x8ee27b94, 0x24430017, 0x37e1021, 0x62102b,
+0x50400001, 0x6b1821, 0x90630000, 0x24020011, 0x14620031, 0x24020006,
+0x8ee27b94, 0x37e1821, 0x24420028, 0x43102b, 0x14400018, 0x0,
+0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 0x3c01ffff, 0x220821,
+0x94220028, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100,
+0x14400004, 0x41027, 0x92e27b88, 0x14400002, 0x41027, 0x3044ffff,
+0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002d82, 0xa4240028, 0x8ee27b8c,
+0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420028, 0x822021, 0x41c02,
+0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88,
+0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0x8002d82, 0xa4440028,
+0x1462002f, 0x37e1821, 0x8ee27b94, 0x24420032, 0x43102b, 0x14400018,
0x0, 0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 0x3c01ffff,
-0x220821, 0x94220028, 0x822021, 0x41c02, 0x3082ffff, 0x622021,
+0x220821, 0x94220032, 0x822021, 0x41c02, 0x3082ffff, 0x622021,
0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 0x14400002, 0x41027,
-0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002cff, 0xa4240028,
-0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420028, 0x822021,
+0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002d82, 0xa4240032,
+0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420032, 0x822021,
0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027,
-0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0x8002cff,
-0xa4440028, 0x1462002f, 0x37e1821, 0x8ee27b94, 0x24420032, 0x43102b,
-0x14400018, 0x0, 0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94,
-0x3c01ffff, 0x220821, 0x94220032, 0x822021, 0x41c02, 0x3082ffff,
-0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 0x14400002,
-0x41027, 0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002cff,
-0xa4240032, 0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420032,
-0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004,
-0x41027, 0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94,
-0xa4440032, 0x8fac0024, 0x1180002c, 0x37e1821, 0x8e420000, 0xae42fffc,
-0x2642000a, 0x43102b, 0x1440001b, 0x34038100, 0x26430004, 0x37e1021,
-0x62102b, 0x14400003, 0x602021, 0x6b1821, 0x602021, 0x8c620000,
-0x24630004, 0xae420000, 0x37e1021, 0x62102b, 0x50400001, 0x6b1821,
-0x8c620000, 0xac820000, 0x34028100, 0xa4620000, 0x24630002, 0x37e1021,
-0x62102b, 0x50400001, 0x6b1821, 0x97ac002e, 0x8002d29, 0xa46c0000,
-0x8e420004, 0x8e440008, 0xa6430008, 0x97ac002e, 0xa64c000a, 0xae420000,
-0xae440004, 0x9662000e, 0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e,
-0x8ee3724c, 0x621821, 0xaee3724c, 0xafb20018, 0x8ee3724c, 0xafa3001c,
-0x8ee2724c, 0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 0x431024,
-0xafa2001c, 0x32c20080, 0x1040000c, 0x32c20100, 0x8ee27b98, 0x24430001,
+0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0xa4440032,
+0x8fac0024, 0x1180002c, 0x37e1821, 0x8e420000, 0xae42fffc, 0x2642000a,
+0x43102b, 0x1440001b, 0x34038100, 0x26430004, 0x37e1021, 0x62102b,
+0x14400003, 0x602021, 0x6b1821, 0x602021, 0x8c620000, 0x24630004,
+0xae420000, 0x37e1021, 0x62102b, 0x50400001, 0x6b1821, 0x8c620000,
+0xac820000, 0x34028100, 0xa4620000, 0x24630002, 0x37e1021, 0x62102b,
+0x50400001, 0x6b1821, 0x97ac002e, 0x8002dac, 0xa46c0000, 0x8e420004,
+0x8e440008, 0xa6430008, 0x97ac002e, 0xa64c000a, 0xae420000, 0xae440004,
+0x9662000e, 0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e, 0x8ee3724c,
+0x621821, 0xaee3724c, 0xafb20018, 0x8ee3724c, 0xafa3001c, 0x8ee2724c,
+0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 0x431024, 0xafa2001c,
+0x32c20080, 0x1040000c, 0x32c20100, 0x8ee27b98, 0x24430001, 0x210c0,
+0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 0xac437b9c, 0xac447ba0,
+0x8002e98, 0xaee0724c, 0x10400072, 0x0, 0x8ee27b98, 0x24430001,
0x210c0, 0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 0xac437b9c,
-0xac447ba0, 0x8002e15, 0xaee0724c, 0x10400072, 0x0, 0x8ee27b98,
-0x24430001, 0x210c0, 0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c,
-0xac437b9c, 0xac447ba0, 0x8ee27b98, 0x10400063, 0x4821, 0x5021,
-0x8f8200f0, 0x24480008, 0x27621800, 0x102102b, 0x50400001, 0x27681000,
-0x8f8200f4, 0x15020007, 0x0, 0x8ee201b0, 0x8021, 0x24420001,
-0xaee201b0, 0x8002d6f, 0x8ee201b0, 0x8f8300f0, 0x24100001, 0x1571021,
-0x8c447b9c, 0x8c457ba0, 0xac640000, 0xac650004, 0xaf8800f0, 0x16000006,
-0x2ea1021, 0x8ee20088, 0x24420001, 0xaee20088, 0x8002db4, 0x8ee20088,
-0x8c427ba0, 0x8ee400e0, 0x8ee500e4, 0x8ee67b8c, 0x401821, 0x1021,
-0xa32821, 0xa3382b, 0x822021, 0x872021, 0x8ee204ec, 0xc93021,
-0x63100, 0xaee400e0, 0xaee500e4, 0xc23021, 0x94c2000a, 0x240c0002,
-0x21142, 0x30430003, 0x106c0016, 0x28620003, 0x10400005, 0x240c0001,
-0x106c0008, 0x0, 0x8002db4, 0x0, 0x240c0003, 0x106c0017,
-0x0, 0x8002db4, 0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001,
-0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8002db4,
-0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 0x441021,
-0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x8002db4, 0x8ee300f4, 0x8ee200f8,
-0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc,
-0x8ee200f8, 0x8ee300fc, 0x8ee27b98, 0x25290001, 0x122102b, 0x1440ffa0,
-0x254a0008, 0xa2e07b88, 0x8002e14, 0xaee07b98, 0x8f8200f0, 0x24470008,
-0x27621800, 0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007,
-0x0, 0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 0x8002dd2,
-0x8ee201b0, 0x8f8200f0, 0x24100001, 0x8fa30018, 0x8fa4001c, 0xac430000,
-0xac440004, 0xaf8700f0, 0x16000007, 0x0, 0x8ee20088, 0x24420001,
-0xaee20088, 0x8ee20088, 0x8002e15, 0xaee0724c, 0x8ee2724c, 0x8ee400e0,
-0x8ee500e4, 0x240c0002, 0x401821, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0x161142, 0x30430003, 0xaee400e0, 0xaee500e4,
-0x106c0017, 0x2c620003, 0x10400005, 0x240c0001, 0x106c0008, 0x0,
-0x8002e15, 0xaee0724c, 0x240c0003, 0x106c0019, 0x0, 0x8002e15,
-0xaee0724c, 0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021,
-0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8ee300ec, 0x8002e15, 0xaee0724c,
+0xac447ba0, 0x8ee27b98, 0x10400063, 0x4821, 0x5021, 0x8f8200f0,
+0x24480008, 0x27621800, 0x102102b, 0x50400001, 0x27681000, 0x8f8200f4,
+0x15020007, 0x0, 0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0,
+0x8002df2, 0x8ee201b0, 0x8f8300f0, 0x24100001, 0x1571021, 0x8c447b9c,
+0x8c457ba0, 0xac640000, 0xac650004, 0xaf8800f0, 0x16000006, 0x2ea1021,
+0x8ee20088, 0x24420001, 0xaee20088, 0x8002e37, 0x8ee20088, 0x8c427ba0,
+0x8ee400e0, 0x8ee500e4, 0x8ee67b8c, 0x401821, 0x1021, 0xa32821,
+0xa3382b, 0x822021, 0x872021, 0x8ee204ec, 0xc93021, 0x63100,
+0xaee400e0, 0xaee500e4, 0xc23021, 0x94c2000a, 0x240c0002, 0x21142,
+0x30430003, 0x106c0016, 0x28620003, 0x10400005, 0x240c0001, 0x106c0008,
+0x0, 0x8002e37, 0x0, 0x240c0003, 0x106c0017, 0x0,
+0x8002e37, 0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001,
+0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8002e37, 0x8ee300ec,
0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 0xaee200f0,
-0xaee300f4, 0x8ee200f0, 0x8ee300f4, 0x8002e15, 0xaee0724c, 0x8ee200f8,
-0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc,
-0x8ee200f8, 0x8ee300fc, 0xaee0724c, 0x8e62001c, 0x96e30458, 0x8ee404e0,
-0x24420001, 0x2463ffff, 0x431024, 0x24840001, 0xaee204d4, 0xaee404e0,
-0x8f42023c, 0x82202b, 0x148000a5, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007,
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002e79,
-0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c,
-0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000,
-0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037,
-0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
-0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8002e63, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x8002e79, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001,
-0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000,
-0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904,
-0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006,
-0xc0023a7, 0xafab0038, 0x8fab0038, 0x16000003, 0x240c0001, 0x8002ec6,
-0xa2ec04e4, 0x8ee2016c, 0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4,
-0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, 0x8f42023c, 0x10400030,
-0x0, 0x8ee20180, 0x24420001, 0xaee20180, 0x8002ec6, 0x8ee20180,
-0x8ee204f4, 0x240c0040, 0x24420001, 0x504c0003, 0x1021, 0x8ee204f4,
-0x24420001, 0xaee204f4, 0x8ee204f4, 0x8e630018, 0x240c0003, 0x21080,
-0x571021, 0x146c000f, 0x8c4404f8, 0x3c020001, 0x571021, 0x904283a1,
-0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, 0x441021, 0xaee201c8,
-0x8ee201cc, 0x641821, 0x306300ff, 0x8002ec1, 0xaee35230, 0x8ee201c4,
-0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, 0x641821, 0x306301ff,
-0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, 0x34420040, 0xaee20000,
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8f820108, 0x27633000,
-0x43102b, 0x14400002, 0x27622800, 0xaf820108, 0x8f830108, 0x8f820104,
-0x1462fc2c, 0x0, 0x8fbf0060, 0x8fbe005c, 0x8fb60058, 0x8fb50054,
-0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, 0x3e00008,
-0x27bd0068, 0x52843, 0x10a0000d, 0x3021, 0x3c030001, 0x34633800,
-0x3c07ffff, 0x3631021, 0x82102b, 0x50400001, 0x872021, 0x94820000,
-0x24840002, 0x24a5ffff, 0x14a0fff8, 0xc23021, 0x61c02, 0x30c2ffff,
-0x623021, 0x61c02, 0x30c2ffff, 0x623021, 0x3e00008, 0x30c2ffff,
-0x0, 0x0, 0x27bdff88, 0x240f0001, 0xafbf0070, 0xafbe006c,
+0xaee300f4, 0x8ee200f0, 0x8002e37, 0x8ee300f4, 0x8ee200f8, 0x8ee300fc,
+0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8,
+0x8ee300fc, 0x8ee27b98, 0x25290001, 0x122102b, 0x1440ffa0, 0x254a0008,
+0xa2e07b88, 0x8002e97, 0xaee07b98, 0x8f8200f0, 0x24470008, 0x27621800,
+0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 0x0,
+0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 0x8002e55, 0x8ee201b0,
+0x8f8200f0, 0x24100001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004,
+0xaf8700f0, 0x16000007, 0x0, 0x8ee20088, 0x24420001, 0xaee20088,
+0x8ee20088, 0x8002e98, 0xaee0724c, 0x8ee2724c, 0x8ee400e0, 0x8ee500e4,
+0x240c0002, 0x401821, 0x1021, 0xa32821, 0xa3302b, 0x822021,
+0x862021, 0x161142, 0x30430003, 0xaee400e0, 0xaee500e4, 0x106c0017,
+0x2c620003, 0x10400005, 0x240c0001, 0x106c0008, 0x0, 0x8002e98,
+0xaee0724c, 0x240c0003, 0x106c0019, 0x0, 0x8002e98, 0xaee0724c,
+0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 0xaee200e8,
+0xaee300ec, 0x8ee200e8, 0x8ee300ec, 0x8002e98, 0xaee0724c, 0x8ee200f0,
+0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 0xaee300f4,
+0x8ee200f0, 0x8ee300f4, 0x8002e98, 0xaee0724c, 0x8ee200f8, 0x8ee300fc,
+0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8,
+0x8ee300fc, 0xaee0724c, 0x8e62001c, 0x96e30458, 0x8ee404e0, 0x24420001,
+0x2463ffff, 0x431024, 0x24840001, 0xaee204d4, 0xaee404e0, 0x8f42023c,
+0x82202b, 0x148000a8, 0x0, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001,
+0xaee201a0, 0x8002eff, 0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0,
+0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
+0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
+0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20,
+0x8ee24e24, 0x1062001b, 0x240c0040, 0x8c820004, 0x24420001, 0xac820004,
+0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 0x0, 0x8ee24e24,
+0x24420001, 0x10620005, 0x0, 0x8002ee9, 0x0, 0x14600005,
+0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
+0x2c420011, 0x50400013, 0xac800000, 0x8002eff, 0x0, 0x8ee24e20,
+0x240c0040, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001,
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012,
+0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4,
+0x3c040001, 0x24844b14, 0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228,
+0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x16000003,
+0x240c0001, 0x8002f4c, 0xa2ec04e4, 0x8ee2016c, 0x24420001, 0xaee2016c,
+0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8,
+0x8f42023c, 0x10400030, 0x0, 0x8ee20180, 0x24420001, 0xaee20180,
+0x8002f4c, 0x8ee20180, 0x8ee204f4, 0x240c0040, 0x24420001, 0x504c0003,
+0x1021, 0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 0x8e630018,
+0x240c0003, 0x21080, 0x571021, 0x146c000f, 0x8c4404f8, 0x3c020001,
+0x571021, 0x904283a1, 0x10400014, 0x0, 0x8ee201c8, 0x8ee35230,
+0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 0x306300ff, 0x8002f47,
+0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc,
+0x641821, 0x306301ff, 0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000,
+0x34420040, 0xaee20000, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108,
+0x8f820108, 0x27633000, 0x43102b, 0x14400002, 0x27622800, 0xaf820108,
+0x8f830108, 0x8f820104, 0x1462fc26, 0x0, 0x8fbf0060, 0x8fbe005c,
+0x8fb60058, 0x8fb50054, 0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044,
+0x8fb00040, 0x3e00008, 0x27bd0068, 0x52843, 0x10a0000d, 0x3021,
+0x3c030001, 0x34633800, 0x3c07ffff, 0x3631021, 0x82102b, 0x50400001,
+0x872021, 0x94820000, 0x24840002, 0x24a5ffff, 0x14a0fff8, 0xc23021,
+0x61c02, 0x30c2ffff, 0x623021, 0x61c02, 0x30c2ffff, 0x623021,
+0x3e00008, 0x30c2ffff, 0x27bdff88, 0x240f0001, 0xafbf0070, 0xafbe006c,
0xafb60068, 0xafb50064, 0xafb40060, 0xafb3005c, 0xafb20058, 0xafb10054,
0xafb00050, 0xa3a00027, 0xafaf002c, 0x8ee204c4, 0x8021, 0x30420001,
0x1440002a, 0xa3a00037, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023,
@@ -1344,30 +1366,30 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023,
0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821,
0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x8003429,
+0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x80034bc,
0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0,
0x3c140001, 0x297a021, 0x8e9483b4, 0x3c130001, 0x2779821, 0x8e7383b8,
-0x3c120001, 0x2579021, 0x80030ff, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4,
+0x3c120001, 0x2579021, 0x8003183, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4,
0x10430007, 0x8821, 0x8f8200e4, 0x24110001, 0x8c430000, 0x8c440004,
0xafa30018, 0xafa4001c, 0x1620000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010,
-0x8f8200c8, 0x3c040001, 0x248449d0, 0xafa20014, 0x8f8600e0, 0x8f8700e4,
-0x3c050006, 0xc0023a7, 0x34a5f000, 0x8003429, 0x0, 0x8fa3001c,
+0x8f8200c8, 0x3c040001, 0x24844be0, 0xafa20014, 0x8f8600e0, 0x8f8700e4,
+0x3c050006, 0xc002403, 0x34a5f000, 0x80034bc, 0x0, 0x8fa3001c,
0x8fb20018, 0x3074ffff, 0x2694fffc, 0x621024, 0x10400058, 0x2409821,
0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001,
-0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x8003423,
+0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x80034b6,
0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008,
0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080,
0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0,
-0x106b0011, 0x0, 0x106a0015, 0x0, 0x8002fb5, 0x42042,
+0x106b0011, 0x0, 0x106a0015, 0x0, 0x8003039, 0x42042,
0x10650023, 0xa3102b, 0x14400005, 0x0, 0x10690019, 0x0,
-0x8002fb5, 0x42042, 0x10680021, 0x0, 0x8002fb5, 0x42042,
-0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x8002fb5, 0x42042,
-0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8002fb5, 0x42042,
-0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x8002fb5, 0x42042,
-0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x8002fb5, 0x42042,
-0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x8002fb5, 0x42042,
-0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x1087046d,
-0x0, 0x8002f7a, 0x0, 0x3c020001, 0x571021, 0x904283a2,
+0x8003039, 0x42042, 0x10680021, 0x0, 0x8003039, 0x42042,
+0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x8003039, 0x42042,
+0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8003039, 0x42042,
+0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x8003039, 0x42042,
+0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x8003039, 0x42042,
+0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x8003039, 0x42042,
+0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x1087047c,
+0x0, 0x8002ffe, 0x0, 0x3c020001, 0x571021, 0x904283a2,
0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f,
0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005,
0x24100001, 0x96430004, 0x3402ffff, 0x10620075, 0x0, 0x92e204c8,
@@ -1376,20 +1398,20 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x2821, 0x96660000, 0x520c0, 0x971021, 0x9442776e, 0x14460009,
0x971021, 0x94437770, 0x96620002, 0x14620005, 0x971021, 0x94437772,
0x96620004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4,
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400431,
-0x0, 0x8003041, 0x0, 0x2402021, 0xc00229d, 0x24050006,
-0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x14400425,
+0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400440,
+0x0, 0x80030c5, 0x0, 0x2402021, 0xc0022f8, 0x24050006,
+0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x14400434,
0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, 0xb71021,
0x94437270, 0x96620002, 0x14620006, 0x418c0, 0xb71021, 0x94437272,
0x96620004, 0x10620035, 0x418c0, 0x2e31021, 0x9442726c, 0x30428000,
-0x14400412, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 0xb71021,
-0x9442736e, 0x8003023, 0x3021, 0x420c0, 0x2e41021, 0x9443736c,
+0x14400421, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 0xb71021,
+0x9442736e, 0x80030a7, 0x3021, 0x420c0, 0x2e41021, 0x9443736c,
0x2e41021, 0x944b736c, 0x30638000, 0x14600010, 0xb28c0, 0xb71021,
0x9442736e, 0x1447fff5, 0x1602021, 0xb71021, 0x94437370, 0x96620002,
0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96620004, 0x5462ffec,
-0x420c0, 0x24060001, 0x30c200ff, 0x104003f1, 0x0, 0x8003041,
-0x0, 0x97430202, 0x96420000, 0x146203eb, 0x0, 0x97430204,
-0x96420002, 0x146203e7, 0x0, 0x97430206, 0x96420004, 0x146203e3,
+0x420c0, 0x24060001, 0x30c200ff, 0x10400400, 0x0, 0x80030c5,
+0x0, 0x97430202, 0x96420000, 0x146203fa, 0x0, 0x97430204,
+0x96420002, 0x146203f6, 0x0, 0x97430206, 0x96420004, 0x146203f2,
0x0, 0x92420000, 0x3a030001, 0x30420001, 0x431024, 0x10400074,
0x2402ffff, 0x8e630000, 0x14620004, 0x3402ffff, 0x96630004, 0x1062006f,
0x240f0002, 0x3c020001, 0x571021, 0x904283a2, 0x1440006a, 0x240f0003,
@@ -1399,33 +1421,33 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x14460009, 0x971021, 0x94437770, 0x96620002, 0x14620005, 0x971021,
0x94437772, 0x96620004, 0x50620008, 0x24070001, 0x3c020001, 0x571021,
0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff,
-0x14400044, 0x240f0003, 0x8003423, 0x0, 0x2402021, 0xc00229d,
+0x14400044, 0x240f0003, 0x80034b6, 0x0, 0x2402021, 0xc0022f8,
0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000,
-0x144003a0, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0,
+0x144003af, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0,
0xb71021, 0x94437270, 0x96620002, 0x14620006, 0x418c0, 0xb71021,
0x94437272, 0x96620004, 0x10620027, 0x418c0, 0x2e31021, 0x9442726c,
-0x30428000, 0x1440038d, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0,
-0xb71021, 0x9442736e, 0x80030a8, 0x3021, 0x420c0, 0x2e41021,
+0x30428000, 0x1440039c, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0,
+0xb71021, 0x9442736e, 0x800312c, 0x3021, 0x420c0, 0x2e41021,
0x9443736c, 0x2e41021, 0x944b736c, 0x30638000, 0x14600010, 0xb28c0,
0xb71021, 0x9442736e, 0x1447fff5, 0x1602021, 0xb71021, 0x94437370,
0x96620002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96620004,
-0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x1040036c, 0x0,
-0x80030bb, 0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260, 0x54102b,
+0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x1040037b, 0x0,
+0x800313f, 0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260, 0x54102b,
0x1040003a, 0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008,
0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2801821, 0x1021,
0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4,
0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001,
0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001,
-0x248449d8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc0023a7,
-0x34a5f003, 0x8003429, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234,
-0x3c040001, 0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006,
-0xc0023a7, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000,
-0x8ee301bc, 0x2403ffbf, 0x431024, 0x80033cd, 0xaee20000, 0x96e20468,
-0x54102b, 0x10400003, 0x0, 0x240f0001, 0xa3af0027, 0x128002f2,
+0x24844be8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403,
+0x34a5f003, 0x80034bc, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234,
+0x3c040001, 0x24844bf4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006,
+0xc002403, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000,
+0x8ee301bc, 0x2403ffbf, 0x431024, 0x8003460, 0xaee20000, 0x96e20468,
+0x54102b, 0x10400003, 0x0, 0x240f0001, 0xa3af0027, 0x12800301,
0x24160007, 0x24150040, 0x241e0001, 0x240e0012, 0x8ee2723c, 0x8f430280,
-0x24420001, 0x304203ff, 0x106202c4, 0x0, 0x93a20027, 0x10400014,
+0x24420001, 0x304203ff, 0x106202d3, 0x0, 0x93a20027, 0x10400014,
0x0, 0x8ee35230, 0x8ee25234, 0x10620009, 0x26ed5234, 0x8ee65234,
-0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x800312b,
+0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x80031af,
0x306b00ff, 0x92e27238, 0x1440ffca, 0x0, 0x8ee201d0, 0x24420001,
0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffc2, 0x26ed0e08,
0x8ee60e08, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28021, 0x24630001,
@@ -1439,28 +1461,29 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x439823, 0x26820007, 0x2404fff8, 0x9603000a, 0x446024, 0x6a1821,
0x6c102b, 0x10400002, 0x1803821, 0x603821, 0xae130018, 0x8f880120,
0x24e20007, 0x443824, 0x27623800, 0x25090020, 0x122102b, 0x50400001,
-0x27693000, 0x8f820128, 0x15220007, 0x1401821, 0x8ee201a0, 0x8821,
-0x24420001, 0xaee201a0, 0x80031b5, 0x8ee201a0, 0x8e040000, 0x8e050004,
-0x1021, 0xad130008, 0xa507000e, 0xad160018, 0xad06001c, 0xa3302b,
-0xa32823, 0x822023, 0x862023, 0xad040000, 0xad050004, 0x8ee204b0,
-0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0,
-0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0,
-0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80031a2, 0x0,
-0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80031b5, 0x0,
-0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001,
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac960000,
-0xac9e0004, 0x16200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x248449f0,
-0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc0023a7,
-0xafa30014, 0x93a20037, 0x1040020a, 0x340f8100, 0x8e420004, 0x8e430008,
-0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004, 0xae440008, 0x96020016,
-0x80033cd, 0xa642000e, 0x14ec015f, 0x28a1823, 0x960c000a, 0x9603000e,
-0x28a1023, 0xa602000a, 0x34620004, 0xa602000e, 0x8f880120, 0x27623800,
-0x25090020, 0x122102b, 0x14400002, 0x306affff, 0x27693000, 0x8f820128,
+0x27693000, 0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007,
+0x1401821, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 0x800323c,
+0x8ee201a0, 0x8e040000, 0x8e050004, 0x1021, 0xad130008, 0xa507000e,
+0xad160018, 0xad06001c, 0xa3302b, 0xa32823, 0x822023, 0x862023,
+0xad040000, 0xad050004, 0x8ee204b0, 0xad020010, 0xaf890120, 0x92e24e10,
+0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
+0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
+0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
+0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
+0x0, 0x8003229, 0x0, 0x14600005, 0x0, 0x8f820128,
+0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
+0xac800000, 0x800323c, 0x0, 0x8ee24e20, 0x24420001, 0x50550003,
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x16200018, 0x3c050006,
+0x8e020018, 0x3c040001, 0x24844c00, 0xafa20010, 0x8e020000, 0x8e030004,
+0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x93a20037, 0x10400216,
+0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000,
+0xae430004, 0xae440008, 0x96020016, 0x8003460, 0xa642000e, 0x14ec0168,
+0x28a1823, 0x960c000a, 0x9603000e, 0x28a1023, 0xa602000a, 0x34620004,
+0xa602000e, 0x8f880120, 0x27623800, 0x25090020, 0x122102b, 0x14400002,
+0x306affff, 0x27693000, 0x8f820128, 0x11220004, 0x0, 0x8f820124,
0x15220007, 0x24040020, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0,
-0x8003230, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e,
+0x80032ba, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e,
0x24040004, 0xad100008, 0xad040018, 0x52940, 0xa01821, 0x1021,
0xe33821, 0xe3202b, 0xc23021, 0xc43021, 0xad060000, 0xad070004,
0x8ee2723c, 0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10,
@@ -1468,278 +1491,280 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x800321d, 0x0, 0x14600005, 0x0, 0x8f820128,
+0x0, 0x80032a7, 0x0, 0x14600005, 0x0, 0x8f820128,
0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x8003230, 0x0, 0x8ee24e20, 0x24420001, 0x50550003,
+0xac800000, 0x80032ba, 0x0, 0x8ee24e20, 0x24420001, 0x50550003,
0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620000d, 0x0,
0xa60c000a, 0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001,
-0x248449fc, 0x3c050006, 0xafa20014, 0x8ee6723c, 0x8003398, 0x34a5f00b,
+0x24844c0c, 0x3c050006, 0xafa20014, 0x8ee6723c, 0x800342b, 0x34a5f00b,
0x3c010001, 0x370821, 0xa02083b0, 0xadab0000, 0x8ee201cc, 0x8ee3723c,
0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x24630001, 0x306303ff, 0x26e25234,
-0x15a20006, 0xaee3723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003255,
+0x15a20006, 0xaee3723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x80032df,
0x8ee201c8, 0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8f420240,
-0x10400070, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240,
-0x43102b, 0x1440016d, 0xa021, 0x8f830120, 0x27623800, 0x24660020,
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0,
-0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 0x80032b2, 0x8ee201a0,
-0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008,
-0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004,
-0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24110001,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144e001f,
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004,
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007,
-0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x800329f,
-0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80032b2,
-0x0, 0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20,
-0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
-0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001, 0x8ee2723c, 0x3c040001,
-0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009,
-0x34a5f008, 0xc0023a7, 0xafae0048, 0x8fae0048, 0x56200001, 0xaee00e0c,
-0x8ee20184, 0x24420001, 0xaee20184, 0x8003328, 0x8ee20184, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
+0x10400073, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240,
+0x43102b, 0x14400176, 0xa021, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001,
+0xaee201a0, 0x800333f, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498,
+0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
+0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
+0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24,
+0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
+0x8ee34e20, 0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001,
+0x10620005, 0x0, 0x800332c, 0x0, 0x14600005, 0x0,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
+0x50400010, 0xac800000, 0x800333f, 0x0, 0x8ee24e20, 0x24420001,
+0x50550003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x5620000d,
+0x24110001, 0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010,
+0x8ee6723c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048,
+0x8fae0048, 0x56200001, 0xaee00e0c, 0x8ee20184, 0x24420001, 0xaee20184,
+0x80033b8, 0x8ee20184, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124,
0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0,
-0x800331a, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c,
+0x80033aa, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c,
0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018,
0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10,
0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8003307, 0x0, 0x14600005, 0x0, 0x8f820128,
+0x0, 0x8003397, 0x0, 0x14600005, 0x0, 0x8f820128,
0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x800331a, 0x0, 0x8ee24e20, 0x24420001, 0x50550003,
+0xac800000, 0x80033aa, 0x0, 0x8ee24e20, 0x24420001, 0x50550003,
0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0,
-0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c,
-0x8f470280, 0x3c050009, 0x34a5f008, 0xc0023a7, 0xafae0048, 0x8fae0048,
-0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x80033cb, 0xa021,
+0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 0x8ee6723c,
+0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048,
+0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x800345e, 0xa021,
0x960c000a, 0x183102b, 0x54400001, 0x1801821, 0xa603000a, 0x8f880120,
0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128,
-0x15220007, 0x24040020, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0,
-0x800338c, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e,
-0x24040004, 0xad100008, 0xad040018, 0x52940, 0xa01821, 0x1021,
-0xe33821, 0xe3202b, 0xc23021, 0xc43021, 0xad060000, 0xad070004,
-0x8ee2723c, 0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10,
-0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
-0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8003379, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x800338c, 0x0, 0x8ee24e20, 0x24420001, 0x50550003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620001d, 0x0,
-0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x248449fc,
-0x3c050006, 0xafa20014, 0x8ee6723c, 0x34a5f00d, 0xc0023a7, 0x2003821,
-0x93a20037, 0x10400031, 0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c,
-0xa64f000c, 0xae420000, 0xae430004, 0xae440008, 0x96020016, 0xa642000e,
-0x9602000e, 0x3042fdff, 0x80033cd, 0xa602000e, 0x8ee201cc, 0x2442ffff,
-0xaee201cc, 0x8ee201cc, 0x8ee201c4, 0x3c04001f, 0x3c010001, 0x370821,
-0xa03e83b0, 0x2442ffff, 0xaee201c4, 0x9603000a, 0x3484ffff, 0x8ee201c4,
-0x6a1821, 0x2639821, 0x93202b, 0x10800003, 0x3c02fff5, 0x34421000,
-0x2629821, 0xadab0000, 0x8ee2723c, 0x24420001, 0x304203ff, 0xaee2723c,
-0x8f420240, 0x10400004, 0x283a023, 0x8ee20e0c, 0x24420001, 0xaee20e0c,
-0xa3a00027, 0x1680fd38, 0x0, 0x12800024, 0x0, 0x3c010001,
-0x370821, 0xac3483b4, 0x3c010001, 0x370821, 0xac3383b8, 0x3c010001,
-0x370821, 0xac3283bc, 0x93a20037, 0x10400008, 0x0, 0x3c020001,
-0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 0xac2283bc,
-0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x14620006, 0x0,
-0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003429, 0x8ee201c0, 0x8ee201b8,
-0x24420001, 0xaee201b8, 0x8003429, 0x8ee201b8, 0x97a4001e, 0x2484fffc,
-0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b,
-0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8faf002c, 0x24020002,
-0x11e2000f, 0x29e20003, 0x14400017, 0x24020003, 0x15e20015, 0x0,
-0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001, 0x441021, 0xaee200d0,
-0xaee300d4, 0x8ee200d0, 0x8003423, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc,
-0x24630001, 0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8,
-0x8003423, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001,
-0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4,
-0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0070,
-0x8fbe006c, 0x8fb60068, 0x8fb50064, 0x8fb40060, 0x8fb3005c, 0x8fb20058,
-0x8fb10054, 0x8fb00050, 0x3e00008, 0x27bd0078, 0x27bdffb0, 0xafb50044,
-0xa821, 0xafb00030, 0x8021, 0xafbf004c, 0xafb60048, 0xafb40040,
-0xafb3003c, 0xafb20038, 0xafb10034, 0x8ee204c4, 0x24140001, 0x30420001,
-0x1440002a, 0xb021, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023,
-0x2c821000, 0x50400001, 0x24841000, 0x420c2, 0x801821, 0x8ee400c8,
-0x8ee500cc, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023,
-0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821,
-0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x80037aa,
-0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0,
-0x3c130001, 0x2779821, 0x8e7383b4, 0x3c110001, 0x2378821, 0x8e3183b8,
-0x3c120001, 0x2579021, 0x8003645, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4,
-0x10430007, 0x4821, 0x8f8200e4, 0x24090001, 0x8c430000, 0x8c440004,
-0xafa30018, 0xafa4001c, 0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010,
-0x8f8200c8, 0x3c040001, 0x248449d0, 0xafa20014, 0x8f8600e0, 0x8f8700e4,
-0x3c050006, 0xc0023a7, 0x34a5f000, 0x80037aa, 0x0, 0x8fa3001c,
-0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, 0x10400058, 0x2408821,
-0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001,
-0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x80037a4,
-0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008,
-0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080,
-0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0,
-0x106b0011, 0x0, 0x106a0015, 0x0, 0x80034ef, 0x42042,
-0x10650023, 0xa3102b, 0x14400005, 0x0, 0x10690019, 0x0,
-0x80034ef, 0x42042, 0x10680021, 0x0, 0x80034ef, 0x42042,
-0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x80034ef, 0x42042,
-0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x80034ef, 0x42042,
-0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x80034ef, 0x42042,
-0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x80034ef, 0x42042,
-0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x80034ef, 0x42042,
-0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x108702b4,
-0x0, 0x80034b4, 0x0, 0x3c020001, 0x571021, 0x904283a2,
-0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f,
-0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005,
-0x24100001, 0x96430004, 0x3402ffff, 0x10620075, 0x0, 0x92e204c8,
-0x14400072, 0x0, 0x3c020001, 0x571021, 0x8c4283a4, 0x28420005,
-0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4, 0x18400016,
-0x2821, 0x96260000, 0x520c0, 0x971021, 0x9442776e, 0x14460009,
-0x971021, 0x94437770, 0x96220002, 0x14620005, 0x971021, 0x94437772,
-0x96220004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4,
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400278,
-0x0, 0x800357b, 0x0, 0x2402021, 0xc00229d, 0x24050006,
-0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x1440026c,
-0xb71021, 0x9443726e, 0x96220000, 0x1462000b, 0x418c0, 0xb71021,
-0x94437270, 0x96220002, 0x14620006, 0x418c0, 0xb71021, 0x94437272,
-0x96220004, 0x10620035, 0x418c0, 0x2e31021, 0x9442726c, 0x30428000,
-0x14400259, 0x2e31021, 0x9448726c, 0x96270000, 0x828c0, 0xb71021,
-0x9442736e, 0x800355d, 0x3021, 0x420c0, 0x2e41021, 0x9443736c,
-0x2e41021, 0x9448736c, 0x30638000, 0x14600010, 0x828c0, 0xb71021,
-0x9442736e, 0x1447fff5, 0x1002021, 0xb71021, 0x94437370, 0x96220002,
-0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96220004, 0x5462ffec,
-0x420c0, 0x24060001, 0x30c200ff, 0x10400238, 0x0, 0x800357b,
-0x0, 0x97430202, 0x96420000, 0x14620232, 0x0, 0x97430204,
-0x96420002, 0x1462022e, 0x0, 0x97430206, 0x96420004, 0x1462022a,
-0x0, 0x92420000, 0x3a030001, 0x30420001, 0x431024, 0x10400074,
-0x2402ffff, 0x8e230000, 0x14620004, 0x3402ffff, 0x96230004, 0x1062006f,
-0x24140002, 0x3c020001, 0x571021, 0x904283a2, 0x1440006a, 0x24140003,
-0x92e204c8, 0x14400067, 0x0, 0x3c020001, 0x571021, 0x8c4283a4,
-0x28420005, 0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4,
-0x18400016, 0x2821, 0x96260000, 0x520c0, 0x971021, 0x9442776e,
-0x14460009, 0x971021, 0x94437770, 0x96220002, 0x14620005, 0x971021,
-0x94437772, 0x96220004, 0x50620008, 0x24070001, 0x3c020001, 0x571021,
-0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff,
-0x14400044, 0x24140003, 0x80037a4, 0x0, 0x2402021, 0xc00229d,
-0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000,
-0x144001e7, 0xb71021, 0x9443726e, 0x96220000, 0x1462000b, 0x418c0,
-0xb71021, 0x94437270, 0x96220002, 0x14620006, 0x418c0, 0xb71021,
-0x94437272, 0x96220004, 0x10620027, 0x418c0, 0x2e31021, 0x9442726c,
-0x30428000, 0x144001d4, 0x2e31021, 0x9448726c, 0x96270000, 0x828c0,
-0xb71021, 0x9442736e, 0x80035e2, 0x3021, 0x420c0, 0x2e41021,
-0x9443736c, 0x2e41021, 0x9448736c, 0x30638000, 0x14600010, 0x828c0,
-0xb71021, 0x9442736e, 0x1447fff5, 0x1002021, 0xb71021, 0x94437370,
-0x96220002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96220004,
-0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x104001b3, 0x0,
-0x80035f5, 0x24140003, 0x24140001, 0x8f420260, 0x53102b, 0x10400049,
-0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4,
-0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2601821, 0x1021, 0xa32821,
-0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058,
-0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c,
-0x8ee2007c, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 0x248449d8,
-0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc0023a7, 0x34a5f003,
-0x80037aa, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, 0x3c040001,
-0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0xc0023a7, 0x34a5f002,
-0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, 0x8ee301bc, 0x2403ffbf,
-0x431024, 0x8003752, 0xaee20000, 0x8ee25230, 0xafa20010, 0x8ee25234,
-0x3c040001, 0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006,
-0xc0023a7, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8003752,
-0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, 0x3c158000, 0x1260012e,
-0x3c0c001f, 0x358cffff, 0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff,
-0x10620105, 0x0, 0x12a00014, 0x0, 0x8ee35230, 0x8ee25234,
-0x10620009, 0x26ee5234, 0x8eeb5234, 0x8ee35234, 0x21140, 0x24425238,
-0x2e28021, 0x24630001, 0x800366f, 0x306800ff, 0x92e27238, 0x1440ffc0,
-0x3c050006, 0x8ee201d0, 0x24420001, 0xaee201d0, 0x8ee201d0, 0x8ee30e00,
-0x8ee20e08, 0x1062ffcb, 0x26ee0e08, 0x8eeb0e08, 0xa821, 0x8ee30e08,
-0x21140, 0x24420e10, 0x2e28021, 0x24630001, 0x306801ff, 0x96e2046a,
-0x30420010, 0x10400017, 0x34028100, 0x9643000c, 0x14620014, 0x0,
-0x3c020001, 0x571021, 0x904283b0, 0x1440000f, 0x0, 0x9642000e,
-0xa6020016, 0x8e420008, 0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c,
-0xae430008, 0xae440004, 0x9602000e, 0x26310004, 0x24160001, 0x34420200,
-0xa602000e, 0x9603000a, 0x2605021, 0x73102b, 0x10400002, 0x2606821,
-0x605021, 0x2d42003d, 0x1040002a, 0x3821, 0x9623000c, 0x24020800,
-0x54620027, 0xae110018, 0x3c020001, 0x571021, 0x904283b0, 0x54400022,
-0xae110018, 0x26220017, 0x182102b, 0x10400013, 0x0, 0x3c02fff5,
-0x511021, 0x90421017, 0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x10600013, 0x26220010, 0x182102b, 0x1040000e, 0x0,
-0x3c07fff5, 0xf13821, 0x94e71010, 0x80036bb, 0x24e7000e, 0x92220017,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600004,
-0xae110018, 0x96270010, 0x24e7000e, 0xae110018, 0x3c020001, 0x571021,
-0x904283b0, 0x2102b, 0x14e00002, 0x24ec0, 0x1403821, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
+0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020, 0x8ee201a0,
+0x8821, 0x24420001, 0xaee201a0, 0x800341f, 0x8ee201a0, 0x8ee5723c,
+0x8ee60480, 0x8ee70484, 0xa504000e, 0x24040004, 0xad100008, 0xad040018,
+0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021,
+0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0xad02001c, 0x8ee204b4,
+0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0,
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001,
+0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0,
+0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x800340c, 0x0,
+0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
+0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x800341f, 0x0,
+0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001,
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac960000,
+0xac9e0004, 0x1620001d, 0x0, 0xa60c000a, 0x8f820100, 0xafa20010,
+0x8f820104, 0x3c040001, 0x24844c0c, 0x3c050006, 0xafa20014, 0x8ee6723c,
+0x34a5f00d, 0xc002403, 0x2003821, 0x93a20037, 0x10400031, 0x340f8100,
+0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004,
+0xae440008, 0x96020016, 0xa642000e, 0x9602000e, 0x3042fdff, 0x8003460,
+0xa602000e, 0x8ee201cc, 0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x8ee201c4,
+0x3c04001f, 0x3c010001, 0x370821, 0xa03e83b0, 0x2442ffff, 0xaee201c4,
+0x9603000a, 0x3484ffff, 0x8ee201c4, 0x6a1821, 0x2639821, 0x93202b,
+0x10800003, 0x3c02fff5, 0x34421000, 0x2629821, 0xadab0000, 0x8ee2723c,
+0x24420001, 0x304203ff, 0xaee2723c, 0x8f420240, 0x10400004, 0x283a023,
+0x8ee20e0c, 0x24420001, 0xaee20e0c, 0xa3a00027, 0x1680fd29, 0x0,
+0x12800024, 0x0, 0x3c010001, 0x370821, 0xac3483b4, 0x3c010001,
+0x370821, 0xac3383b8, 0x3c010001, 0x370821, 0xac3283bc, 0x93a20037,
+0x10400008, 0x0, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004,
+0x3c010001, 0x370821, 0xac2283bc, 0x8ee2723c, 0x8f430280, 0x24420001,
+0x304203ff, 0x14620006, 0x0, 0x8ee201c0, 0x24420001, 0xaee201c0,
+0x80034bc, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, 0x80034bc,
+0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4,
+0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0,
+0xaee500c4, 0x8faf002c, 0x24020002, 0x11e2000f, 0x29e20003, 0x14400017,
+0x24020003, 0x15e20015, 0x0, 0x8ee200d0, 0x8ee300d4, 0x24630001,
+0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x80034b6,
+0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 0x441021,
+0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x80034b6, 0x8ee300dc, 0x8ee200c8,
+0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 0xaee300cc,
+0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008,
+0xaf8300e4, 0xaf8300e8, 0x8fbf0070, 0x8fbe006c, 0x8fb60068, 0x8fb50064,
+0x8fb40060, 0x8fb3005c, 0x8fb20058, 0x8fb10054, 0x8fb00050, 0x3e00008,
+0x27bd0078, 0x27bdffb0, 0xafb50044, 0xa821, 0xafb00030, 0x8021,
+0xafbf004c, 0xafb60048, 0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034,
+0x8ee204c4, 0x24140001, 0x30420001, 0x1440002a, 0xb021, 0x8f8700e0,
+0x8f8800c4, 0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001, 0x24841000,
+0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc, 0x1021, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8,
+0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a,
+0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021,
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4,
+0xaf8800c8, 0xaf8700e4, 0x8003840, 0xaf8700e8, 0x3c020001, 0x571021,
+0x904283b0, 0x1040000b, 0x0, 0x3c130001, 0x2779821, 0x8e7383b4,
+0x3c110001, 0x2378821, 0x8e3183b8, 0x3c120001, 0x2579021, 0x80036d8,
+0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x4821, 0x8f8200e4,
+0x24090001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1520000e,
+0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844be0,
+0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000,
+0x8003840, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc,
+0x621024, 0x10400058, 0x2408821, 0x3c020080, 0x621024, 0x1040000a,
+0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8ee201ec,
+0x24420001, 0xaee201ec, 0x800383a, 0x8ee201ec, 0x3c060004, 0x3c0b0001,
+0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000,
+0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021,
+0xc3102b, 0x14400007, 0x0, 0x106b0011, 0x0, 0x106a0015,
+0x0, 0x8003582, 0x42042, 0x10650023, 0xa3102b, 0x14400005,
+0x0, 0x10690019, 0x0, 0x8003582, 0x42042, 0x10680021,
+0x0, 0x8003582, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034,
+0x8ee20034, 0x8003582, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc,
+0x8ee201dc, 0x8003582, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0,
+0x8ee201e0, 0x8003582, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4,
+0x8ee201e4, 0x8003582, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030,
+0x8ee20030, 0x8003582, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8,
+0x8ee201e8, 0x42042, 0x108702b7, 0x0, 0x8003547, 0x0,
+0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001,
+0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024,
+0x1040006f, 0x2402ffff, 0x14620005, 0x24100001, 0x96430004, 0x3402ffff,
+0x10620075, 0x0, 0x92e204c8, 0x14400072, 0x0, 0x3c020001,
+0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, 0x3c020001,
+0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96260000, 0x520c0,
+0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96220002,
+0x14620005, 0x971021, 0x94437772, 0x96220004, 0x50620008, 0x24070001,
+0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee,
+0x520c0, 0x30e200ff, 0x1040027b, 0x0, 0x800360e, 0x0,
+0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021,
+0x9442726c, 0x30424000, 0x1440026f, 0xb71021, 0x9443726e, 0x96220000,
+0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96220002, 0x14620006,
+0x418c0, 0xb71021, 0x94437272, 0x96220004, 0x10620035, 0x418c0,
+0x2e31021, 0x9442726c, 0x30428000, 0x1440025c, 0x2e31021, 0x9448726c,
+0x96270000, 0x828c0, 0xb71021, 0x9442736e, 0x80035f0, 0x3021,
+0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x9448736c, 0x30638000,
+0x14600010, 0x828c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1002021,
+0xb71021, 0x94437370, 0x96220002, 0x5462fff1, 0x420c0, 0xb71021,
+0x94437372, 0x96220004, 0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff,
+0x1040023b, 0x0, 0x800360e, 0x0, 0x97430202, 0x96420000,
+0x14620235, 0x0, 0x97430204, 0x96420002, 0x14620231, 0x0,
+0x97430206, 0x96420004, 0x1462022d, 0x0, 0x92420000, 0x3a030001,
+0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e230000, 0x14620004,
+0x3402ffff, 0x96230004, 0x1062006f, 0x24140002, 0x3c020001, 0x571021,
+0x904283a2, 0x1440006a, 0x24140003, 0x92e204c8, 0x14400067, 0x0,
+0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821,
+0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96260000,
+0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770,
+0x96220002, 0x14620005, 0x971021, 0x94437772, 0x96220004, 0x50620008,
+0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a,
+0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24140003, 0x800383a,
+0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0,
+0x2e51021, 0x9442726c, 0x30424000, 0x144001ea, 0xb71021, 0x9443726e,
+0x96220000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96220002,
+0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96220004, 0x10620027,
+0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x144001d7, 0x2e31021,
+0x9448726c, 0x96270000, 0x828c0, 0xb71021, 0x9442736e, 0x8003675,
+0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x9448736c,
+0x30638000, 0x14600010, 0x828c0, 0xb71021, 0x9442736e, 0x1447fff5,
+0x1002021, 0xb71021, 0x94437370, 0x96220002, 0x5462fff1, 0x420c0,
+0xb71021, 0x94437372, 0x96220004, 0x5462ffec, 0x420c0, 0x24060001,
+0x30c200ff, 0x104001b6, 0x0, 0x8003688, 0x24140003, 0x24140001,
+0x8f420260, 0x53102b, 0x10400049, 0x0, 0x8f8300e4, 0x8f8200e0,
+0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4,
+0x2601821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021,
+0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058,
+0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010,
+0x8f8200e4, 0x3c040001, 0x24844be8, 0xafa20014, 0x8fa60018, 0x8fa7001c,
+0x3c050006, 0xc002403, 0x34a5f003, 0x8003840, 0x0, 0x8ee25230,
+0xafa20010, 0x8ee25234, 0x3c040001, 0x24844bf4, 0xafa20014, 0x8ee60e00,
+0x8ee70e08, 0xc002403, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc,
+0x8ee20000, 0x8ee301bc, 0x2403ffbf, 0x431024, 0x80037e8, 0xaee20000,
+0x8ee25230, 0xafa20010, 0x8ee25234, 0x3c040001, 0x24844bf4, 0xafa20014,
+0x8ee60e00, 0x8ee70e08, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201bc,
+0x24420001, 0xaee201bc, 0x80037e8, 0x8ee201bc, 0x96e20468, 0x53102b,
+0x54400001, 0x3c158000, 0x12600131, 0x3c0c001f, 0x358cffff, 0x8ee2723c,
+0x8f430280, 0x24420001, 0x304203ff, 0x10620108, 0x0, 0x12a00014,
+0x0, 0x8ee35230, 0x8ee25234, 0x10620009, 0x26ee5234, 0x8eeb5234,
+0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x8003702,
+0x306800ff, 0x92e27238, 0x1440ffc0, 0x3c050006, 0x8ee201d0, 0x24420001,
+0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffcb, 0x26ee0e08,
+0x8eeb0e08, 0xa821, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28021,
+0x24630001, 0x306801ff, 0x96e2046a, 0x30420010, 0x10400017, 0x34028100,
+0x9643000c, 0x14620014, 0x0, 0x3c020001, 0x571021, 0x904283b0,
+0x1440000f, 0x0, 0x9642000e, 0xa6020016, 0x8e420008, 0x8e430004,
+0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 0x9602000e,
+0x26310004, 0x24160001, 0x34420200, 0xa602000e, 0x9603000a, 0x2605021,
+0x73102b, 0x10400002, 0x2606821, 0x605021, 0x2d42003d, 0x1040002a,
+0x3821, 0x9623000c, 0x24020800, 0x54620027, 0xae110018, 0x3c020001,
+0x571021, 0x904283b0, 0x54400022, 0xae110018, 0x26220017, 0x182102b,
+0x10400013, 0x0, 0x3c02fff5, 0x511021, 0x90421017, 0x38430006,
+0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x10600013, 0x26220010,
+0x182102b, 0x1040000e, 0x0, 0x3c07fff5, 0xf13821, 0x94e71010,
+0x800374e, 0x24e7000e, 0x92220017, 0x38430006, 0x2c630001, 0x38420011,
+0x2c420001, 0x621825, 0x50600004, 0xae110018, 0x96270010, 0x24e7000e,
+0xae110018, 0x3c020001, 0x571021, 0x904283b0, 0x2102b, 0x14e00002,
+0x24ec0, 0x1403821, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b,
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124,
0x14c20007, 0x2402000b, 0x8ee201a0, 0x4821, 0x24420001, 0xaee201a0,
-0x8003719, 0x8ee201a0, 0x8e040000, 0x8e050004, 0xac620018, 0x1751025,
+0x80037af, 0x8ee201a0, 0x8e040000, 0x8e050004, 0xac620018, 0x1751025,
0x491025, 0xac710008, 0xa467000e, 0xac62001c, 0xac640000, 0xac650004,
0x8ee204b0, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400038, 0x24090001,
0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007,
0x14620020, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001c, 0x0,
0x8c820004, 0x24420001, 0xac820004, 0x8ee34e24, 0x8ee54e20, 0x24020040,
0x24630001, 0x10620007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005,
-0x0, 0x8003703, 0x0, 0x14a00005, 0x0, 0x8f820128,
+0x0, 0x8003799, 0x0, 0x14a00005, 0x0, 0x8f820128,
0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x8003719, 0x0, 0x8ee24e20, 0x24030040, 0x24420001,
+0xac800000, 0x80037af, 0x0, 0x8ee24e20, 0x24030040, 0x24420001,
0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001,
-0xac820004, 0x15200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x248449f0,
-0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc0023a7,
+0xac820004, 0x15200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x24844c00,
+0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403,
0xafa30014, 0x32c200ff, 0x1040002b, 0x34028100, 0x8e430004, 0x8e440008,
0x8e45000c, 0xa642000c, 0xae430000, 0xae440004, 0xae450008, 0x96020016,
-0x8003752, 0xa642000e, 0x154d000a, 0x0, 0x9602000e, 0xa613000a,
-0x34420004, 0xa602000e, 0x3c010001, 0x370821, 0xa02083b0, 0x8003750,
+0x80037e8, 0xa642000e, 0x154d000a, 0x0, 0x9602000e, 0xa613000a,
+0x34420004, 0xa602000e, 0x3c010001, 0x370821, 0xa02083b0, 0x80037e6,
0x9821, 0x9604000a, 0x93102b, 0x10400002, 0x2601821, 0x801821,
0x24020001, 0xa603000a, 0x3c010001, 0x370821, 0xa02283b0, 0x9604000a,
0x2248821, 0x191102b, 0x10400003, 0x3c02fff5, 0x34421000, 0x2228821,
-0x2649823, 0xa821, 0x1660fef7, 0xadc80000, 0x12600021, 0x32c200ff,
+0x2649823, 0xa821, 0x1660fef4, 0xadc80000, 0x12600021, 0x32c200ff,
0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 0x370821, 0xac3183b8,
0x3c010001, 0x370821, 0x10400008, 0xac3283bc, 0x3c020001, 0x571021,
0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 0xac2283bc, 0x8ee2723c,
0x8f430280, 0x24420001, 0x14620006, 0x0, 0x8ee201c0, 0x24420001,
-0xaee201c0, 0x80037aa, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8,
-0x80037aa, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0,
+0xaee201c0, 0x8003840, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8,
+0x8003840, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0,
0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021,
0x24020002, 0xaee400c0, 0xaee500c4, 0x1282000f, 0x2a820003, 0x14400017,
0x24020003, 0x16820015, 0x0, 0x8ee200d0, 0x8ee300d4, 0x24630001,
-0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x80037a4,
+0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x800383a,
0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 0x441021,
-0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x80037a4, 0x8ee300dc, 0x8ee200c8,
+0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x800383a, 0x8ee300dc, 0x8ee200c8,
0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 0xaee300cc,
0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008,
0xaf8300e4, 0xaf8300e8, 0x8fbf004c, 0x8fb60048, 0x8fb50044, 0x8fb40040,
0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050,
-0x27bdff90, 0xafbe0064, 0xf021, 0xafbf0068, 0xafb60060, 0xafb5005c,
+0x27bdff90, 0xafb60060, 0xb021, 0xafbf0068, 0xafbe0064, 0xafb5005c,
0xafb40058, 0xafb30054, 0xafb20050, 0xafb1004c, 0xafb00048, 0x8ee204c4,
-0x8821, 0x24160001, 0x30420001, 0x1440002a, 0xa3a0002f, 0x8f8700e0,
+0x8821, 0x24150001, 0x30420001, 0x1440002a, 0xa3a0002f, 0x8f8700e0,
0x8f8800c4, 0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001, 0x24841000,
0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc, 0x1021, 0xa32821,
0xa3302b, 0x822021, 0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8,
0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a,
0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021,
0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4,
-0xaf8800c8, 0xaf8700e4, 0x8003bb3, 0xaf8700e8, 0x3c020001, 0x571021,
+0xaf8800c8, 0xaf8700e4, 0x8003c4b, 0xaf8700e8, 0x3c020001, 0x571021,
0x904283b0, 0x1040000b, 0x0, 0x3c130001, 0x2779821, 0x8e7383b4,
-0x3c100001, 0x2178021, 0x8e1083b8, 0x3c120001, 0x2579021, 0x80039b3,
+0x3c100001, 0x2178021, 0x8e1083b8, 0x3c120001, 0x2579021, 0x8003a49,
0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x3821, 0x8f8200e4,
0x24070001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x14e0000e,
-0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844a14,
-0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc0023a7, 0x34a5f200,
-0x8003bb3, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc,
+0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844c24,
+0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f200,
+0x8003c4b, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc,
0x621024, 0x10400058, 0x2408021, 0x3c020080, 0x621024, 0x1040000a,
0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8ee201ec,
-0x24420001, 0xaee201ec, 0x8003bad, 0x8ee201ec, 0x3c060004, 0x3c0b0001,
+0x24420001, 0xaee201ec, 0x8003c45, 0x8ee201ec, 0x3c060004, 0x3c0b0001,
0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000,
0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021,
0xc3102b, 0x14400007, 0x0, 0x106b0011, 0x0, 0x106a0015,
-0x0, 0x8003870, 0x42042, 0x10650023, 0xa3102b, 0x14400005,
-0x0, 0x10690019, 0x0, 0x8003870, 0x42042, 0x10680021,
-0x0, 0x8003870, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034,
-0x8ee20034, 0x8003870, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc,
-0x8ee201dc, 0x8003870, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0,
-0x8ee201e0, 0x8003870, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4,
-0x8ee201e4, 0x8003870, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030,
-0x8ee20030, 0x8003870, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8,
-0x8ee201e8, 0x42042, 0x1087033c, 0x0, 0x8003835, 0x0,
+0x0, 0x8003906, 0x42042, 0x10650023, 0xa3102b, 0x14400005,
+0x0, 0x10690019, 0x0, 0x8003906, 0x42042, 0x10680021,
+0x0, 0x8003906, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034,
+0x8ee20034, 0x8003906, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc,
+0x8ee201dc, 0x8003906, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0,
+0x8ee201e0, 0x8003906, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4,
+0x8ee201e4, 0x8003906, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030,
+0x8ee20030, 0x8003906, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8,
+0x8ee201e8, 0x42042, 0x1087033e, 0x0, 0x80038cb, 0x0,
0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001,
0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024,
0x1040006f, 0x2402ffff, 0x14620005, 0x24110001, 0x96430004, 0x3402ffff,
@@ -1749,491 +1774,487 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96020002,
0x14620005, 0x971021, 0x94437772, 0x96020004, 0x50620008, 0x24070001,
0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee,
-0x520c0, 0x30e200ff, 0x10400300, 0x0, 0x80038fc, 0x0,
-0x2402021, 0xc00229d, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021,
-0x9442726c, 0x30424000, 0x144002f4, 0xb71021, 0x9443726e, 0x96020000,
+0x520c0, 0x30e200ff, 0x10400302, 0x0, 0x8003992, 0x0,
+0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021,
+0x9442726c, 0x30424000, 0x144002f6, 0xb71021, 0x9443726e, 0x96020000,
0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96020002, 0x14620006,
0x418c0, 0xb71021, 0x94437272, 0x96020004, 0x10620035, 0x418c0,
-0x2e31021, 0x9442726c, 0x30428000, 0x144002e1, 0x2e31021, 0x944e726c,
-0x96070000, 0xe28c0, 0xb71021, 0x9442736e, 0x80038de, 0x3021,
-0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944e736c, 0x30638000,
-0x14600010, 0xe28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1c02021,
+0x2e31021, 0x9442726c, 0x30428000, 0x144002e3, 0x2e31021, 0x944d726c,
+0x96070000, 0xd28c0, 0xb71021, 0x9442736e, 0x8003974, 0x3021,
+0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944d736c, 0x30638000,
+0x14600010, 0xd28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1a02021,
0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, 0xb71021,
0x94437372, 0x96020004, 0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff,
-0x104002c0, 0x0, 0x80038fc, 0x0, 0x97430202, 0x96420000,
-0x146202ba, 0x0, 0x97430204, 0x96420002, 0x146202b6, 0x0,
-0x97430206, 0x96420004, 0x146202b2, 0x0, 0x92420000, 0x3a230001,
+0x104002c2, 0x0, 0x8003992, 0x0, 0x97430202, 0x96420000,
+0x146202bc, 0x0, 0x97430204, 0x96420002, 0x146202b8, 0x0,
+0x97430206, 0x96420004, 0x146202b4, 0x0, 0x92420000, 0x3a230001,
0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e030000, 0x14620004,
-0x3402ffff, 0x96030004, 0x1062006f, 0x24160002, 0x3c020001, 0x571021,
-0x904283a2, 0x1440006a, 0x24160003, 0x92e204c8, 0x14400067, 0x0,
+0x3402ffff, 0x96030004, 0x1062006f, 0x24150002, 0x3c020001, 0x571021,
+0x904283a2, 0x1440006a, 0x24150003, 0x92e204c8, 0x14400067, 0x0,
0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821,
0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96060000,
0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770,
0x96020002, 0x14620005, 0x971021, 0x94437772, 0x96020004, 0x50620008,
0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a,
-0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24160003, 0x8003bad,
-0x0, 0x2402021, 0xc00229d, 0x24050006, 0x3044001f, 0x428c0,
-0x2e51021, 0x9442726c, 0x30424000, 0x1440026f, 0xb71021, 0x9443726e,
+0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24150003, 0x8003c45,
+0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0,
+0x2e51021, 0x9442726c, 0x30424000, 0x14400271, 0xb71021, 0x9443726e,
0x96020000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96020002,
0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96020004, 0x10620027,
-0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x1440025c, 0x2e31021,
-0x944e726c, 0x96070000, 0xe28c0, 0xb71021, 0x9442736e, 0x8003963,
-0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944e736c,
-0x30638000, 0x14600010, 0xe28c0, 0xb71021, 0x9442736e, 0x1447fff5,
-0x1c02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0,
+0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x1440025e, 0x2e31021,
+0x944d726c, 0x96070000, 0xd28c0, 0xb71021, 0x9442736e, 0x80039f9,
+0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944d736c,
+0x30638000, 0x14600010, 0xd28c0, 0xb71021, 0x9442736e, 0x1447fff5,
+0x1a02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0,
0xb71021, 0x94437372, 0x96020004, 0x5462ffec, 0x420c0, 0x24060001,
-0x30c200ff, 0x1040023b, 0x0, 0x8003976, 0x24160003, 0x24160001,
+0x30c200ff, 0x1040023d, 0x0, 0x8003a0c, 0x24150003, 0x24150001,
0x8f420260, 0x53102b, 0x10400036, 0x0, 0x8f8300e4, 0x8f8200e0,
0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4,
0x2601821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021,
0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058,
0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010,
-0x8f8200e4, 0x3c040001, 0x24844a20, 0xafa20014, 0x8fa60018, 0x8fa7001c,
-0x3c050006, 0xc0023a7, 0x34a5f203, 0x8003bb3, 0x0, 0x8ee25230,
-0xafa20010, 0x8ee25234, 0x3c040001, 0x24844a2c, 0xafa20014, 0x8ee60e00,
-0x8ee70e08, 0x3c050006, 0xc0023a7, 0x34a5f202, 0x8ee201bc, 0x24420001,
-0xaee201bc, 0x8003b5a, 0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001,
-0x3c1e8000, 0x126001c9, 0x3c0f001f, 0x35efffff, 0x3c18fff5, 0x37181000,
-0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x1062019d, 0x0,
-0x13c00012, 0x0, 0x8ee35230, 0x8ee25234, 0x1062000a, 0x26f95234,
-0x8ef55234, 0xafb90024, 0x8ee35234, 0x21140, 0x24425238, 0x2e28821,
-0x24630001, 0x80039de, 0x306e00ff, 0x8ee201d0, 0x24420001, 0xaee201d0,
-0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffcb, 0x26f90e08, 0x8ef50e08,
-0xf021, 0xafb90024, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28821,
-0x24630001, 0x306e01ff, 0x96e2046a, 0x30420010, 0x10400018, 0x34028100,
-0x9643000c, 0x14620015, 0x0, 0x3c020001, 0x571021, 0x904283b0,
-0x14400010, 0x0, 0x9642000e, 0xa6220016, 0x8e420008, 0x8e430004,
-0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 0x9622000e,
-0x26100004, 0x24190001, 0xa3b9002f, 0x34420200, 0xa622000e, 0x8e220000,
-0x8e230004, 0x3c040001, 0x34843800, 0x2003021, 0x306b0007, 0x20b8023,
-0x3641021, 0x202102b, 0x10400005, 0x26b9821, 0x2041023, 0x3621823,
-0x3c020020, 0x438023, 0x26620007, 0x9623000a, 0x2419fff8, 0x59a024,
-0x6b1821, 0x74102b, 0x10400002, 0x2806821, 0x606821, 0x1a01821,
-0x24620007, 0x2419fff8, 0x596824, 0x26d102b, 0x14400004, 0x1b32823,
-0x1a32823, 0x8003a1c, 0xc31021, 0xd31021, 0x4b2023, 0x1e4102b,
-0x54400001, 0x982021, 0x25620040, 0x4d102b, 0x14400035, 0x6021,
-0x94c3000c, 0x24020800, 0x54620032, 0xae260018, 0x3c020001, 0x571021,
-0x904283b0, 0x5440002d, 0xae260018, 0x24c20017, 0x1e2102b, 0x10400013,
-0x0, 0x3c02fff5, 0x461021, 0x90421017, 0x38430006, 0x2c630001,
-0x38420011, 0x2c420001, 0x621825, 0x10600014, 0x24c20010, 0x1e2102b,
-0x1040000e, 0x0, 0x3c0cfff5, 0x1866021, 0x958c1010, 0x8003a4d,
-0x2582000e, 0x90c20017, 0x38430006, 0x2c630001, 0x38420011, 0x2c420001,
-0x621825, 0x10600005, 0x1801821, 0x94cc0010, 0x2582000e, 0x4b6021,
-0x1801821, 0x24620007, 0x2419fff8, 0x596024, 0xc31021, 0x4b2023,
-0x1e4102b, 0x10400002, 0x1832823, 0x982021, 0xae260018, 0x3c020001,
-0x571021, 0x904283b0, 0x2102b, 0x216c0, 0x15800002, 0xafa20044,
-0x1a06021, 0x30820001, 0x10400007, 0x4021, 0x90880000, 0x24840001,
-0x1e4102b, 0x10400002, 0x24a5ffff, 0x982021, 0x50a00012, 0x81c02,
+0x8f8200e4, 0x3c040001, 0x24844c30, 0xafa20014, 0x8fa60018, 0x8fa7001c,
+0x3c050006, 0xc002403, 0x34a5f203, 0x8003c4b, 0x0, 0x8ee25230,
+0xafa20010, 0x8ee25234, 0x3c040001, 0x24844c3c, 0xafa20014, 0x8ee60e00,
+0x8ee70e08, 0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201bc, 0x24420001,
+0xaee201bc, 0x8003bf2, 0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001,
+0x3c168000, 0x126001cb, 0x3c0e001f, 0x35ceffff, 0x3c0ffff5, 0x35ef1000,
+0x241e0040, 0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x1062019e,
+0x0, 0x12c00012, 0x0, 0x8ee35230, 0x8ee25234, 0x1062000a,
+0x26f85234, 0x8ef45234, 0xafb80024, 0x8ee35234, 0x21140, 0x24425238,
+0x2e28821, 0x24630001, 0x8003a75, 0x306d00ff, 0x8ee201d0, 0x24420001,
+0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffca, 0x26f80e08,
+0x8ef40e08, 0xb021, 0xafb80024, 0x8ee30e08, 0x21140, 0x24420e10,
+0x2e28821, 0x24630001, 0x306d01ff, 0x96e2046a, 0x30420010, 0x10400018,
+0x34028100, 0x9643000c, 0x14620015, 0x0, 0x3c020001, 0x571021,
+0x904283b0, 0x14400010, 0x0, 0x9642000e, 0xa6220016, 0x8e420008,
+0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004,
+0x9622000e, 0x26100004, 0x24180001, 0xa3b8002f, 0x34420200, 0xa622000e,
+0x8e220000, 0x8e230004, 0x3c040001, 0x34843800, 0x2003021, 0x306a0007,
+0x20a8023, 0x3641021, 0x202102b, 0x10400005, 0x26a9821, 0x2041023,
+0x3621823, 0x3c020020, 0x438023, 0x26620007, 0x9623000a, 0x2418fff8,
+0x58c824, 0x6a1821, 0x79102b, 0x10400002, 0x3206021, 0x606021,
+0x1801821, 0x24620007, 0x2418fff8, 0x586024, 0x26c102b, 0x14400004,
+0x1932823, 0x1832823, 0x8003ab3, 0xc31021, 0xd31021, 0x4a2023,
+0x1c4102b, 0x54400001, 0x8f2021, 0x25420040, 0x4c102b, 0x14400035,
+0x5821, 0x94c3000c, 0x24020800, 0x54620032, 0xae260018, 0x3c020001,
+0x571021, 0x904283b0, 0x5440002d, 0xae260018, 0x24c20017, 0x1c2102b,
+0x10400013, 0x0, 0x3c02fff5, 0x461021, 0x90421017, 0x38430006,
+0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x10600014, 0x24c20010,
+0x1c2102b, 0x1040000e, 0x0, 0x3c0bfff5, 0x1665821, 0x956b1010,
+0x8003ae4, 0x2562000e, 0x90c20017, 0x38430006, 0x2c630001, 0x38420011,
+0x2c420001, 0x621825, 0x10600005, 0x1601821, 0x94cb0010, 0x2562000e,
+0x4a5821, 0x1601821, 0x24620007, 0x2418fff8, 0x585824, 0xc31021,
+0x4a2023, 0x1c4102b, 0x10400002, 0x1632823, 0x8f2021, 0xae260018,
+0x3c020001, 0x571021, 0x904283b0, 0x2102b, 0x216c0, 0x15600002,
+0xafa20044, 0x1805821, 0x30820001, 0x10400007, 0x4021, 0x90880000,
+0x24840001, 0x1c4102b, 0x10400002, 0x24a5ffff, 0x8f2021, 0x50a00012,
+0x81c02, 0x2ca20002, 0x54400009, 0x24a5ffff, 0x94820000, 0x24840002,
+0x1024021, 0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b11, 0x8f2021,
+0x90820000, 0x21200, 0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02,
+0x3102ffff, 0x624021, 0x3108ffff, 0x1402821, 0x11400011, 0x2002021,
0x2ca20002, 0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 0x1024021,
-0x1e4102b, 0x10400006, 0x24a5fffe, 0x8003a7a, 0x982021, 0x90820000,
+0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b28, 0x8f2021, 0x90820000,
0x21200, 0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff,
-0x624021, 0x3108ffff, 0x1602821, 0x11600011, 0x2002021, 0x2ca20002,
-0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 0x1024021, 0x1e4102b,
-0x10400006, 0x24a5fffe, 0x8003a91, 0x982021, 0x90820000, 0x21200,
-0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff, 0x624021,
-0x81c02, 0x3102ffff, 0x8f890120, 0x624021, 0x27623800, 0x252a0020,
-0x142102b, 0x14400002, 0x3108ffff, 0x276a3000, 0x8f820128, 0x15420007,
-0x1602821, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8003b21,
-0x8ee201a0, 0x8e260000, 0x8e270004, 0x81400, 0x3443000b, 0xad300008,
-0xa52c000e, 0xad230018, 0x8fb90044, 0x2021, 0x2be1025, 0x591025,
-0xad22001c, 0xe5102b, 0xe53823, 0xc43023, 0xc23023, 0xad260000,
-0xad270004, 0x8ee204b0, 0xad220010, 0xaf8a0120, 0x92e24e10, 0x14400061,
-0x24070001, 0x2462ffee, 0x2c420002, 0x14400003, 0x24020011, 0x14620025,
-0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
-0x24020012, 0x1462000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b,
-0x24190040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x1059002b, 0x0, 0x8003aff, 0x0, 0x8ee24e20,
-0x24190040, 0x24420001, 0x50590003, 0x1021, 0x8ee24e20, 0x24420001,
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8003b1e,
-0x24020012, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
-0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x24190040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x10590007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8003b0b, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013,
-0xac800000, 0x8003b21, 0x0, 0x8ee24e20, 0x24190040, 0x24420001,
-0x50590003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001,
-0xac820004, 0x14e00019, 0x3c050006, 0x3c040001, 0x248449f0, 0x8e220018,
-0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x1803821,
-0xc0023a7, 0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100, 0x8e430004,
-0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000, 0xae440004, 0xae450008,
-0x96220016, 0x8003b5a, 0xa642000e, 0x15b4000a, 0x26b1823, 0x9622000e,
-0xa623000a, 0x34420004, 0xa622000e, 0x3c010001, 0x370821, 0xa02083b0,
-0x8003b57, 0x9821, 0x9624000a, 0x83102b, 0x54400001, 0x801821,
-0x24020001, 0xa623000a, 0x3c010001, 0x370821, 0xa02283b0, 0x9622000a,
-0x4b1821, 0x2038021, 0x1f0102b, 0x54400001, 0x2188021, 0x2639823,
-0xf021, 0x8fb90024, 0x1660fe5f, 0xaf2e0000, 0x12600022, 0x0,
-0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 0x370821, 0xac3083b8,
-0x3c010001, 0x370821, 0xac3283bc, 0x93a2002f, 0x10400008, 0x0,
-0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821,
-0xac2283bc, 0x8f430280, 0x8ee2723c, 0x14620006, 0x0, 0x8ee201c0,
-0x24420001, 0xaee201c0, 0x8003bb3, 0x8ee201c0, 0x8ee201b8, 0x24420001,
-0xaee201b8, 0x8003bb3, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821,
-0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021,
-0x862021, 0x24020002, 0xaee400c0, 0xaee500c4, 0x12c2000f, 0x2ac20003,
-0x14400017, 0x24020003, 0x16c20015, 0x0, 0x8ee200d0, 0x8ee300d4,
-0x24630001, 0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0,
-0x8003bad, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001,
-0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x8003bad, 0x8ee300dc,
-0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8,
-0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003,
-0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0068, 0x8fbe0064, 0x8fb60060,
-0x8fb5005c, 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048,
-0x3e00008, 0x27bd0070, 0x27bdffe0, 0xafbf0018, 0x8ee30e04, 0x8ee20dfc,
-0x10620071, 0x0, 0x8ee30dfc, 0x8ee20e04, 0x622023, 0x4820001,
-0x24840200, 0x8ee30e08, 0x8ee20e04, 0x43102b, 0x14400004, 0x24020200,
-0x8ee30e04, 0x8003bd5, 0x431823, 0x8ee20e08, 0x8ee30e04, 0x431023,
+0x624021, 0x81c02, 0x3102ffff, 0x8f890120, 0x624021, 0x27623800,
+0x25230020, 0x62102b, 0x14400002, 0x3108ffff, 0x27633000, 0x8f820128,
+0x10620004, 0x0, 0x8f820124, 0x14620007, 0x1402821, 0x8ee201a0,
+0x3821, 0x24420001, 0xaee201a0, 0x8003bb9, 0x8ee201a0, 0x8e260000,
+0x8e270004, 0x81400, 0x3448000b, 0xad300008, 0xa52b000e, 0xad280018,
+0x8fb80044, 0x2021, 0x2961025, 0x581025, 0xad22001c, 0xe5102b,
+0xe53823, 0xc43023, 0xc23023, 0xad260000, 0xad270004, 0x8ee204b0,
+0xad220010, 0xaf830120, 0x92e24e10, 0x1440005f, 0x24070001, 0x2502ffee,
+0x2c420002, 0x14400003, 0x24020011, 0x15020024, 0x0, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462000f,
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 0x0, 0x8c820004,
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x105e002a,
+0x0, 0x8003b98, 0x0, 0x8ee24e20, 0x24420001, 0x505e0003,
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0x8003bb6, 0x24020012, 0x8ee24e20, 0x210c0,
+0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0,
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001,
+0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x105e0007, 0x0,
+0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8003ba4, 0x0,
+0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
+0x8c820004, 0x2c420011, 0x50400012, 0xac800000, 0x8003bb9, 0x0,
+0x8ee24e20, 0x24420001, 0x505e0003, 0x1021, 0x8ee24e20, 0x24420001,
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007,
+0xac820000, 0x24020001, 0xac820004, 0x14e00019, 0x3c050006, 0x3c040001,
+0x24844c00, 0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004,
+0x2203021, 0x1603821, 0xc002403, 0xafa30014, 0x93a2002f, 0x1040002a,
+0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000,
+0xae440004, 0xae450008, 0x96220016, 0x8003bf2, 0xa642000e, 0x1599000a,
+0x26a1823, 0x9622000e, 0xa623000a, 0x34420004, 0xa622000e, 0x3c010001,
+0x370821, 0xa02083b0, 0x8003bef, 0x9821, 0x9624000a, 0x83102b,
+0x54400001, 0x801821, 0x24020001, 0xa623000a, 0x3c010001, 0x370821,
+0xa02283b0, 0x9622000a, 0x4a1821, 0x2038021, 0x1d0102b, 0x54400001,
+0x20f8021, 0x2639823, 0xb021, 0x8fb80024, 0x1660fe5e, 0xaf0d0000,
+0x12600022, 0x0, 0x3c010001, 0x370821, 0xac3383b4, 0x3c010001,
+0x370821, 0xac3083b8, 0x3c010001, 0x370821, 0xac3283bc, 0x93a2002f,
+0x10400008, 0x0, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004,
+0x3c010001, 0x370821, 0xac2283bc, 0x8f430280, 0x8ee2723c, 0x14620006,
+0x0, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003c4b, 0x8ee201c0,
+0x8ee201b8, 0x24420001, 0xaee201b8, 0x8003c4b, 0x8ee201b8, 0x97a4001e,
+0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0x24020002, 0xaee400c0, 0xaee500c4,
+0x12a2000f, 0x2aa20003, 0x14400017, 0x24020003, 0x16a20015, 0x0,
+0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001, 0x441021, 0xaee200d0,
+0xaee300d4, 0x8ee200d0, 0x8003c45, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc,
+0x24630001, 0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8,
+0x8003c45, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001,
+0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4,
+0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0068,
+0x8fbe0064, 0x8fb60060, 0x8fb5005c, 0x8fb40058, 0x8fb30054, 0x8fb20050,
+0x8fb1004c, 0x8fb00048, 0x3e00008, 0x27bd0070, 0x27bdffe0, 0xafbf0018,
+0x8ee30e04, 0x8ee20dfc, 0x10620074, 0x0, 0x8ee30dfc, 0x8ee20e04,
+0x622023, 0x4820001, 0x24840200, 0x8ee30e08, 0x8ee20e04, 0x43102b,
+0x14400004, 0x24020200, 0x8ee30e04, 0x8003c6d, 0x431823, 0x8ee20e08,
+0x8ee30e04, 0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001,
+0x604821, 0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001,
+0x27682800, 0x8f820108, 0x11020004, 0x0, 0x8f820104, 0x15020007,
+0x1021, 0x8ee201a4, 0x2021, 0x24420001, 0xaee201a4, 0x8003caf,
+0x8ee201a4, 0x8ee40e04, 0x42140, 0x801821, 0x8ee40460, 0x8ee50464,
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004,
+0x8ee30e04, 0x91140, 0xa4e2000e, 0x24020002, 0xace20018, 0x31940,
+0x24630e10, 0x2e31021, 0xace20008, 0x8ee20e04, 0xace2001c, 0x8ee204bc,
+0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 0x24040001, 0x8ee24e18,
+0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001,
+0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020002,
+0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee20e04,
+0xafa20010, 0x8ee20e08, 0x3c050007, 0xafa20014, 0x8ee60dfc, 0x8ee70e00,
+0x3c040001, 0x24844c44, 0xc002403, 0x34a5f001, 0x8003ccd, 0x0,
+0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 0x8ee204f0, 0x24420001,
+0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 0xac4904f8, 0x8ee20e04,
+0x491021, 0x304201ff, 0xaee20e04, 0x8ee30e04, 0x8ee20dfc, 0x14620005,
+0x0, 0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8ee3522c, 0x8ee25228,
+0x10620074, 0x0, 0x8ee35228, 0x8ee2522c, 0x622023, 0x4820001,
+0x24840100, 0x8ee35234, 0x8ee2522c, 0x43102b, 0x14400004, 0x24020100,
+0x8ee3522c, 0x8003cef, 0x431823, 0x8ee25234, 0x8ee3522c, 0x431023,
0x2443ffff, 0x804821, 0x69102a, 0x54400001, 0x604821, 0x8f870100,
0x27623000, 0x24e80020, 0x102102b, 0x50400001, 0x27682800, 0x8f820108,
-0x15020007, 0x1021, 0x8ee201a4, 0x2021, 0x24420001, 0xaee201a4,
-0x8003c14, 0x8ee201a4, 0x8ee40e04, 0x42140, 0x801821, 0x8ee40460,
-0x8ee50464, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000,
-0xace50004, 0x8ee30e04, 0x91140, 0xa4e2000e, 0x24020002, 0xace20018,
-0x31940, 0x24630e10, 0x2e31021, 0xace20008, 0x8ee20e04, 0xace2001c,
-0x8ee204bc, 0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 0x24040001,
-0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18,
-0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821,
-0x24020002, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040,
-0x8ee20e04, 0xafa20010, 0x8ee20e08, 0x3c050007, 0xafa20014, 0x8ee60dfc,
-0x8ee70e00, 0x3c040001, 0x24844a34, 0xc0023a7, 0x34a5f001, 0x8003c32,
-0x0, 0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 0x8ee204f0,
-0x24420001, 0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 0xac4904f8,
-0x8ee20e04, 0x491021, 0x304201ff, 0xaee20e04, 0x8ee30e04, 0x8ee20dfc,
-0x14620005, 0x0, 0x8f820060, 0x2403fdff, 0x431024, 0xaf820060,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8ee3522c,
-0x8ee25228, 0x10620071, 0x0, 0x8ee35228, 0x8ee2522c, 0x622023,
-0x4820001, 0x24840100, 0x8ee35234, 0x8ee2522c, 0x43102b, 0x14400004,
-0x24020100, 0x8ee3522c, 0x8003c54, 0x431823, 0x8ee25234, 0x8ee3522c,
-0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001, 0x604821,
-0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001, 0x27682800,
-0x8f820108, 0x15020007, 0x1021, 0x8ee201a4, 0x2021, 0x24420001,
-0xaee201a4, 0x8003c93, 0x8ee201a4, 0x8ee4522c, 0x42140, 0x801821,
-0x8ee40470, 0x8ee50474, 0xa32821, 0xa3302b, 0x822021, 0x862021,
-0xace40000, 0xace50004, 0x8ee3522c, 0x91140, 0xa4e2000e, 0x24020003,
-0xace20018, 0x31940, 0x24635238, 0x2e31021, 0xace20008, 0x8ee2522c,
-0xace2001c, 0x8ee204bc, 0xace20010, 0xaf880100, 0x92e204dc, 0x14400011,
-0x24040001, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28,
-0x2e21821, 0x24020003, 0xac620000, 0x24020001, 0xac620004, 0x1480000e,
-0x24030040, 0x8ee2522c, 0xafa20010, 0x8ee25234, 0x3c050007, 0xafa20014,
-0x8ee65228, 0x8ee75230, 0x3c040001, 0x24844a40, 0xc0023a7, 0x34a5f010,
-0x8003cb1, 0x0, 0x8ee204f0, 0x24420001, 0x50430003, 0x1021,
-0x8ee204f0, 0x24420001, 0xaee204f0, 0x8ee204f0, 0x21080, 0x571021,
-0xac4904f8, 0x8ee2522c, 0x491021, 0x304200ff, 0xaee2522c, 0x8ee3522c,
-0x8ee25228, 0x14620005, 0x0, 0x8f820060, 0x2403feff, 0x431024,
-0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f820120, 0x8ee34e24,
-0x8f820124, 0x8f860128, 0x24020040, 0x24630001, 0x50620003, 0x1021,
-0x8ee24e24, 0x24420001, 0xaee24e24, 0x8ee24e24, 0x8ee44e24, 0x8ee34e20,
-0x210c0, 0x24425028, 0x14830007, 0x2e22821, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8003ce4, 0xaca00000, 0x8ee24e24, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ee24e24, 0x24420001, 0x210c0,
-0x24425028, 0x2e22821, 0x8ca20004, 0x8f830128, 0x21140, 0x621821,
-0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012, 0x10400008,
-0x31080, 0x3c010001, 0x220821, 0x8c224a50, 0x400008, 0x0,
-0x24020001, 0xaee24e14, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0030,
-0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018,
-0x8f830128, 0x8f820124, 0x106202a7, 0xa021, 0x3c11001f, 0x3631ffff,
-0x3c12fff5, 0x36521000, 0x24150012, 0x24130040, 0x8f8c0128, 0x8f820128,
-0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe, 0x2c620012,
-0x10400293, 0x31080, 0x3c010001, 0x220821, 0x8c224aa8, 0x400008,
-0x0, 0x8f420218, 0x30420100, 0x10400007, 0x0, 0x95830016,
-0x95820018, 0x621823, 0x31402, 0x431021, 0xa5820016, 0x8d82001c,
-0x3c038000, 0x3044ffff, 0x436824, 0x3c030800, 0x431824, 0x11a00004,
-0xad84001c, 0x41140, 0x8003d2a, 0x24425238, 0x41140, 0x24420e10,
-0x2e25821, 0x9562000e, 0x3042fffc, 0x10600004, 0xa562000e, 0x95840016,
-0x8003e12, 0x0, 0x8d690018, 0x4021, 0x952a0000, 0x25290002,
-0x95270000, 0x25290002, 0x95260000, 0x25290002, 0x95250000, 0x25290002,
-0x95240000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002,
-0x1475021, 0x1465021, 0x1455021, 0x1445021, 0x1435021, 0x1425021,
-0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, 0x625021,
-0x96e2046a, 0x314effff, 0x30420002, 0x10400044, 0x5021, 0x25220014,
-0x222102b, 0x10400014, 0x1201821, 0x2405000a, 0x2021, 0x223102b,
-0x54400001, 0x721821, 0x94620000, 0x24630002, 0x24a5ffff, 0x14a0fff9,
-0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x41402, 0x3083ffff,
-0x431021, 0x3042ffff, 0x8003d85, 0x1425021, 0x952a0000, 0x25290002,
-0x95280000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002,
-0x95250000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002,
-0x95240000, 0x25290002, 0x1485021, 0x1475021, 0x1465021, 0x1455021,
-0x1435021, 0x1425021, 0x95220000, 0x95230002, 0x1445021, 0x1425021,
-0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff,
-0x625021, 0x3148ffff, 0x51000001, 0x3408ffff, 0x8d620018, 0x9443000c,
-0x24020800, 0x54620005, 0xa5680010, 0x9562000e, 0x34420002, 0xa562000e,
-0xa5680010, 0x96e2046a, 0x2821, 0x30420008, 0x14400056, 0x3021,
-0x8d630018, 0x24620024, 0x222102b, 0x10400034, 0x24690010, 0x229102b,
-0x54400001, 0x1324821, 0x95250000, 0x24690014, 0x229102b, 0x10400002,
-0x24a5ffec, 0x1324821, 0x95220000, 0x30420fff, 0x14400003, 0x25290002,
-0x8003db2, 0x24140001, 0xa021, 0xa03021, 0x229102b, 0x54400001,
-0x1324821, 0x91220001, 0x25290002, 0xa22821, 0x229102b, 0x54400001,
-0x1324821, 0x25290002, 0x229102b, 0x54400001, 0x1324821, 0x95220000,
-0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000,
-0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000,
-0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000,
-0x8003deb, 0xa22821, 0x94650010, 0x94620014, 0x24690016, 0x30420fff,
-0x14400003, 0x24a5ffec, 0x8003dde, 0x24140001, 0xa021, 0xa03021,
-0x91230001, 0x25290004, 0x95220000, 0x25290002, 0x95240000, 0x25290002,
-0xa32821, 0xa22821, 0x95220000, 0x95230002, 0xa42821, 0xa22821,
-0xa32821, 0x51c02, 0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff,
-0x622821, 0x96e2046a, 0x30420001, 0x1040001e, 0x2021, 0x95820016,
-0x4e2023, 0x41402, 0x822021, 0x328200ff, 0x50400002, 0x862021,
-0x852021, 0x41402, 0x822021, 0x3084ffff, 0x50800001, 0x3404ffff,
-0x8d620018, 0x24430017, 0x223102b, 0x54400001, 0x721821, 0x90620000,
-0x38430011, 0x2c630001, 0x38420006, 0x2c420001, 0x621825, 0x10600004,
-0x0, 0x9562000e, 0x34420001, 0xa562000e, 0x9562000e, 0x240a0002,
-0x30420004, 0x10400002, 0xa5640012, 0x240a0004, 0x8f880120, 0x27623800,
-0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, 0x15220007,
-0x24040020, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003e9e,
-0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xad0b0008, 0xa504000e,
-0xad0a0018, 0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b,
-0xc23021, 0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0x4d1025,
-0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400060,
-0x24100001, 0x2543ffee, 0x2c630002, 0x39420011, 0x2c420001, 0x621825,
-0x10600024, 0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
-0x8c820000, 0x1455000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b,
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x1053002b, 0x0, 0x8003e7d, 0x0, 0x8ee24e20,
-0x24420001, 0x50530003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20,
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0x8003e9d,
-0xac950000, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000,
-0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8003e89, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400012,
-0xac800000, 0x8003e9e, 0x0, 0x8ee24e20, 0x24420001, 0x50530003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x1600000d, 0x0, 0x8f820120, 0x3c040001, 0x24844a98, 0xafa00014,
-0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008, 0xc0023a7, 0x34a50001,
-0x8003fa0, 0x0, 0x8ee2723c, 0x24420001, 0x304203ff, 0x11a00006,
-0xaee2723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003eba, 0x8ee201c8,
-0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8ee201cc, 0x2442ffff,
-0xaee201cc, 0x8003fa0, 0x8ee201cc, 0x8f420240, 0x104000df, 0x0,
-0x8ee20e0c, 0x24420001, 0x8003fa0, 0xaee20e0c, 0x9582001e, 0xad82001c,
-0x8f420240, 0x1040006f, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c,
-0x8f430240, 0x43102b, 0x144000cf, 0x0, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007,
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003f26,
+0x11020004, 0x0, 0x8f820104, 0x15020007, 0x1021, 0x8ee201a4,
+0x2021, 0x24420001, 0xaee201a4, 0x8003d31, 0x8ee201a4, 0x8ee4522c,
+0x42140, 0x801821, 0x8ee40470, 0x8ee50474, 0xa32821, 0xa3302b,
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee3522c, 0x91140,
+0xa4e2000e, 0x24020003, 0xace20018, 0x31940, 0x24635238, 0x2e31021,
+0xace20008, 0x8ee2522c, 0xace2001c, 0x8ee204bc, 0xace20010, 0xaf880100,
+0x92e204dc, 0x14400011, 0x24040001, 0x8ee24e18, 0x24030040, 0x24420001,
+0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18,
+0x210c0, 0x24424e28, 0x2e21821, 0x24020003, 0xac620000, 0x24020001,
+0xac620004, 0x1480000e, 0x24030040, 0x8ee2522c, 0xafa20010, 0x8ee25234,
+0x3c050007, 0xafa20014, 0x8ee65228, 0x8ee75230, 0x3c040001, 0x24844c50,
+0xc002403, 0x34a5f010, 0x8003d4f, 0x0, 0x8ee204f0, 0x24420001,
+0x50430003, 0x1021, 0x8ee204f0, 0x24420001, 0xaee204f0, 0x8ee204f0,
+0x21080, 0x571021, 0xac4904f8, 0x8ee2522c, 0x491021, 0x304200ff,
+0xaee2522c, 0x8ee3522c, 0x8ee25228, 0x14620005, 0x0, 0x8f820060,
+0x2403feff, 0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020,
+0x8f820120, 0x8ee34e24, 0x8f820124, 0x8f860128, 0x24020040, 0x24630001,
+0x50620003, 0x1021, 0x8ee24e24, 0x24420001, 0xaee24e24, 0x8ee24e24,
+0x8ee44e24, 0x8ee34e20, 0x210c0, 0x24425028, 0x14830007, 0x2e22821,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8003d82, 0xaca00000,
+0x8ee24e24, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e24,
+0x24420001, 0x210c0, 0x24425028, 0x2e22821, 0x8ca20004, 0x8f830128,
+0x21140, 0x621821, 0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe,
+0x2c620012, 0x10400008, 0x31080, 0x3c010001, 0x220821, 0x8c224c60,
+0x400008, 0x0, 0x24020001, 0xaee24e14, 0x3e00008, 0x0,
+0x27bdffc8, 0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020,
+0xafb1001c, 0xafb00018, 0x8f830128, 0x8f820124, 0x106202b0, 0x9821,
+0x3c11001f, 0x3631ffff, 0x3c12fff5, 0x36521000, 0x24150012, 0x24140040,
+0x8f8c0128, 0x8f820128, 0x24420020, 0xaf820128, 0x9182001b, 0x8f830128,
+0x2443fffe, 0x2c620012, 0x1040029c, 0x31080, 0x3c010001, 0x220821,
+0x8c224cb8, 0x400008, 0x0, 0x8f420218, 0x30420100, 0x10400007,
+0x0, 0x95830016, 0x95820018, 0x621823, 0x31402, 0x431021,
+0xa5820016, 0x8d82001c, 0x3c038000, 0x3044ffff, 0x436824, 0x3c030800,
+0x431824, 0x11a00004, 0xad84001c, 0x41140, 0x8003dc8, 0x24425238,
+0x41140, 0x24420e10, 0x2e25821, 0x9562000e, 0x3042fffc, 0x10600004,
+0xa562000e, 0x95840016, 0x8003eb0, 0x0, 0x8d690018, 0x4021,
+0x952a0000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002,
+0x95250000, 0x25290002, 0x95240000, 0x25290002, 0x95230000, 0x25290002,
+0x95220000, 0x25290002, 0x1475021, 0x1465021, 0x1455021, 0x1445021,
+0x1435021, 0x1425021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02,
+0x3142ffff, 0x625021, 0x96e2046a, 0x314effff, 0x30420002, 0x10400044,
+0x5021, 0x25220014, 0x222102b, 0x10400014, 0x1201821, 0x2405000a,
+0x2021, 0x223102b, 0x54400001, 0x721821, 0x94620000, 0x24630002,
+0x24a5ffff, 0x14a0fff9, 0x822021, 0x41c02, 0x3082ffff, 0x622021,
+0x41402, 0x3083ffff, 0x431021, 0x3042ffff, 0x8003e23, 0x1425021,
+0x952a0000, 0x25290002, 0x95280000, 0x25290002, 0x95270000, 0x25290002,
+0x95260000, 0x25290002, 0x95250000, 0x25290002, 0x95230000, 0x25290002,
+0x95220000, 0x25290002, 0x95240000, 0x25290002, 0x1485021, 0x1475021,
+0x1465021, 0x1455021, 0x1435021, 0x1425021, 0x95220000, 0x95230002,
+0x1445021, 0x1425021, 0x1435021, 0xa1c02, 0x3142ffff, 0x625021,
+0xa1c02, 0x3142ffff, 0x625021, 0x3148ffff, 0x51000001, 0x3408ffff,
+0x8d620018, 0x9443000c, 0x24020800, 0x54620005, 0xa5680010, 0x9562000e,
+0x34420002, 0xa562000e, 0xa5680010, 0x96e2046a, 0x2821, 0x30420008,
+0x14400056, 0x3021, 0x8d630018, 0x24620024, 0x222102b, 0x10400034,
+0x24690010, 0x229102b, 0x54400001, 0x1324821, 0x95250000, 0x24690014,
+0x229102b, 0x10400002, 0x24a5ffec, 0x1324821, 0x95220000, 0x30420fff,
+0x14400003, 0x25290002, 0x8003e50, 0x24130001, 0x9821, 0xa03021,
+0x229102b, 0x54400001, 0x1324821, 0x91220001, 0x25290002, 0xa22821,
+0x229102b, 0x54400001, 0x1324821, 0x25290002, 0x229102b, 0x54400001,
+0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001,
+0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001,
+0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001,
+0x1324821, 0x95220000, 0x8003e89, 0xa22821, 0x94650010, 0x94620014,
+0x24690016, 0x30420fff, 0x14400003, 0x24a5ffec, 0x8003e7c, 0x24130001,
+0x9821, 0xa03021, 0x91230001, 0x25290004, 0x95220000, 0x25290002,
+0x95240000, 0x25290002, 0xa32821, 0xa22821, 0x95220000, 0x95230002,
+0xa42821, 0xa22821, 0xa32821, 0x51c02, 0x30a2ffff, 0x622821,
+0x51c02, 0x30a2ffff, 0x622821, 0x96e2046a, 0x30420001, 0x1040001e,
+0x2021, 0x95820016, 0x4e2023, 0x41402, 0x822021, 0x326200ff,
+0x50400002, 0x862021, 0x852021, 0x41402, 0x822021, 0x3084ffff,
+0x50800001, 0x3404ffff, 0x8d620018, 0x24430017, 0x223102b, 0x54400001,
+0x721821, 0x90620000, 0x38430011, 0x2c630001, 0x38420006, 0x2c420001,
+0x621825, 0x10600004, 0x0, 0x9562000e, 0x34420001, 0xa562000e,
+0x9562000e, 0x240a0002, 0x30420004, 0x10400002, 0xa5640012, 0x240a0004,
+0x8f880120, 0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000,
+0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020,
+0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003f3f, 0x8ee201a0,
+0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xad0b0008, 0xa504000e, 0xad0a0018,
+0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021,
+0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0x4d1025, 0xad02001c,
+0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400060, 0x24100001,
+0x2543ffee, 0x2c630002, 0x39420011, 0x2c420001, 0x621825, 0x10600024,
+0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
+0x1455000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 0x0,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
+0x1054002b, 0x0, 0x8003f1e, 0x0, 0x8ee24e20, 0x24420001,
+0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0x8003f3e, 0xac950000,
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007,
+0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
+0x10540007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
+0x8003f2a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400012, 0xac800000,
+0x8003f3f, 0x0, 0x8ee24e20, 0x24420001, 0x50540003, 0x1021,
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x1600000d,
+0x0, 0x8f820120, 0x3c040001, 0x24844ca8, 0xafa00014, 0xafa20010,
+0x8d86001c, 0x8f870124, 0x3c050008, 0xc002403, 0x34a50001, 0x8004047,
+0x0, 0x8ee2723c, 0x24420001, 0x304203ff, 0x11a00006, 0xaee2723c,
+0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003f5b, 0x8ee201c8, 0x8ee201c4,
+0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8ee201cc, 0x2442ffff, 0xaee201cc,
+0x8004047, 0x8ee201cc, 0x8f420240, 0x104000e5, 0x0, 0x8ee20e0c,
+0x24420001, 0x8004047, 0xaee20e0c, 0x9582001e, 0xad82001c, 0x8f420240,
+0x10400072, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240,
+0x43102b, 0x144000d5, 0x0, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001,
+0xaee201a0, 0x8003fca, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498,
+0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011,
+0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120,
+0x92e24e10, 0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24,
+0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24,
+0x8ee34e20, 0x24420001, 0x10540007, 0x0, 0x8ee24e24, 0x24420001,
+0x10620005, 0x0, 0x8003fb6, 0x0, 0x14600005, 0x0,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011,
+0x50400011, 0xac800000, 0x8003fca, 0x0, 0x8ee24e20, 0x24420001,
+0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20,
+0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0xac950000, 0xac820004,
+0x5600000b, 0x24100001, 0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014,
+0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008,
+0x56000001, 0xaee00e0c, 0x8ee20184, 0x24420001, 0xaee20184, 0x8004040,
+0x8ee20184, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001,
+0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007,
+0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8004034,
0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c,
0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000,
0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400034,
0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
-0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
-0x8003f12, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0x10540007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
+0x8004020, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400011, 0xac800000,
-0x8003f26, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, 0x1021,
+0x8004034, 0x0, 0x8ee24e20, 0x24420001, 0x50540003, 0x1021,
0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
-0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x5600000b, 0x24100001,
-0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c,
-0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 0x56000001, 0xaee00e0c,
-0x8ee20184, 0x24420001, 0xaee20184, 0x8003f99, 0x8ee20184, 0x8f830120,
-0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128,
-0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0,
-0x8003f8d, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c,
-0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018,
-0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10,
-0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
-0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8003f79, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400011,
-0xac800000, 0x8003f8d, 0x0, 0x8ee24e20, 0x24420001, 0x50530003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b,
-0x0, 0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010,
-0x8ee6723c, 0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 0x8ee20170,
-0x24420001, 0xaee20170, 0x8003fa0, 0x8ee20170, 0x24020001, 0xaee24e14,
-0x8f830128, 0x8f820124, 0x1462fd61, 0x0, 0x8fbf0030, 0x8fb5002c,
-0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0038, 0x0, 0x0, 0x0, 0x27bdffe8, 0x27840208,
-0x27450200, 0x24060008, 0xafbf0014, 0xc00243e, 0xafb00010, 0x24040001,
-0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204, 0xaf820214,
-0x8f460248, 0x24030004, 0x3c020040, 0x3c010001, 0xac234de8, 0x3c010001,
-0xac234dec, 0x3c010001, 0xac204e8c, 0x3c010001, 0xac224de4, 0x3c010001,
-0xac234dec, 0xc004e2c, 0x24050004, 0xc0046b4, 0x0, 0x8ee20000,
-0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00, 0xaf82021c,
-0x3c010001, 0x370821, 0xac30839c, 0x8fbf0014, 0x8fb00010, 0x3e00008,
-0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010,
-0xafa00014, 0x8f860200, 0x3c040001, 0x24844b50, 0xc0023a7, 0x3821,
-0x8ee20270, 0x24420001, 0xaee20270, 0x8ee20270, 0x8f830200, 0x3c023f00,
-0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8,
-0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f900220, 0x8ee20204, 0x3821,
-0x24420001, 0xaee20204, 0x8ee20204, 0x3c020300, 0x2021024, 0x10400027,
-0x3c110400, 0xc0041e7, 0x0, 0x3c020100, 0x2021024, 0x10400007,
-0x0, 0x8ee20208, 0x24420001, 0xaee20208, 0x8ee20208, 0x8004012,
-0x3c03fdff, 0x8ee2020c, 0x24420001, 0xaee2020c, 0x8ee2020c, 0x3c03fdff,
-0x3463ffff, 0x3c0808ff, 0x3508ffff, 0x8ee20000, 0x3c040001, 0x24844b5c,
-0x3c050008, 0x2003021, 0x431024, 0xaee20000, 0x8f820220, 0x3821,
-0x3c030300, 0x481024, 0x431025, 0xaf820220, 0xafa00010, 0xc0023a7,
-0xafa00014, 0x80041e2, 0x0, 0x2111024, 0x1040001f, 0x3c024000,
-0x8f830224, 0x24021402, 0x1462000b, 0x3c03fdff, 0x3c040001, 0x24844b68,
-0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc0023a7,
-0x3821, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x2002021, 0x431024,
-0xc004b88, 0xaee20000, 0x8ee20210, 0x24420001, 0xaee20210, 0x8ee20210,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x80041e1, 0x511025,
-0x2021024, 0x10400142, 0x0, 0x8ee2021c, 0x24420001, 0xaee2021c,
-0x8ee2021c, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004,
-0xaf820220, 0x8f830054, 0x8f820054, 0x800405a, 0x24630002, 0x8f820054,
-0x621023, 0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x8f8400e4,
+0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, 0x0,
+0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 0x8ee6723c,
+0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20170, 0x24420001,
+0xaee20170, 0x8004047, 0x8ee20170, 0x24020001, 0xaee24e14, 0x8f830128,
+0x8f820124, 0x1462fd58, 0x0, 0x8fbf0030, 0x8fb5002c, 0x8fb40028,
+0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038,
+0x27bdffe8, 0x27840208, 0x27450200, 0x24060008, 0xafbf0014, 0xc00249a,
+0xafb00010, 0x24040001, 0x24100001, 0x2402241f, 0xaf900210, 0xaf900200,
+0xaf800204, 0xaf820214, 0x8f460248, 0x24030004, 0x3c020040, 0x3c010001,
+0xac234ff8, 0x3c010001, 0xac234ffc, 0x3c010001, 0xac20509c, 0x3c010001,
+0xac224ff4, 0x3c010001, 0xac234ffc, 0xc004eac, 0x24050004, 0xc004734,
+0x0, 0x8ee20000, 0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000,
+0x3c023c00, 0xaf82021c, 0x3c010001, 0x370821, 0xac30839c, 0x8fbf0014,
+0x8fb00010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400,
+0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001, 0x24844d60,
+0xc002403, 0x3821, 0x8ee20270, 0x24420001, 0xaee20270, 0x8ee20270,
+0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008,
+0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f900220,
+0x8ee20204, 0x3821, 0x24420001, 0xaee20204, 0x8ee20204, 0x3c020300,
+0x2021024, 0x10400027, 0x3c110400, 0xc00428b, 0x0, 0x3c020100,
+0x2021024, 0x10400007, 0x0, 0x8ee20208, 0x24420001, 0xaee20208,
+0x8ee20208, 0x80040b6, 0x3c03fdff, 0x8ee2020c, 0x24420001, 0xaee2020c,
+0x8ee2020c, 0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff, 0x8ee20000,
+0x3c040001, 0x24844d6c, 0x3c050008, 0x2003021, 0x431024, 0xaee20000,
+0x8f820220, 0x3821, 0x3c030300, 0x481024, 0x431025, 0xaf820220,
+0xafa00010, 0xc002403, 0xafa00014, 0x8004286, 0x0, 0x2111024,
+0x1040001f, 0x3c024000, 0x8f830224, 0x24021402, 0x1462000b, 0x3c03fdff,
+0x3c040001, 0x24844d78, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224,
+0x34a5ffff, 0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000, 0x3463ffff,
+0x2002021, 0x431024, 0xc004c08, 0xaee20000, 0x8ee20210, 0x24420001,
+0xaee20210, 0x8ee20210, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
+0x8004285, 0x511025, 0x2021024, 0x10400142, 0x0, 0x8ee2021c,
+0x24420001, 0xaee2021c, 0x8ee2021c, 0x8f820220, 0x3c0308ff, 0x3463ffff,
+0x431024, 0x34420004, 0xaf820220, 0x8f830054, 0x8f820054, 0x80040fe,
+0x24630002, 0x8f820054, 0x621023, 0x2c420003, 0x1440fffc, 0x0,
+0x8f8600e0, 0x8f8400e4, 0x30c20007, 0x10400012, 0x0, 0x8f8300e4,
+0x2402fff8, 0xc21024, 0x1043000d, 0x0, 0x8f820054, 0x8f8300e0,
+0x14c30009, 0x24440050, 0x8f820054, 0x821023, 0x2c420051, 0x10400004,
+0x0, 0x8f8200e0, 0x10c2fff9, 0x0, 0x8f820220, 0x3c0308ff,
+0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0, 0x30c20007, 0x10400003,
+0x2402fff8, 0xc23024, 0xaf8600e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff,
+0x24680008, 0x48102b, 0x10400003, 0x3c02fff5, 0x34421000, 0x1024021,
+0x8f8b00c8, 0x8f850120, 0x8f840124, 0x8004135, 0x6021, 0x27623800,
+0x82102b, 0x50400001, 0x27643000, 0x10a40010, 0x318200ff, 0x8c820018,
+0x38430007, 0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 0x5060fff3,
+0x24840020, 0x8ee20230, 0x240c0001, 0x24420001, 0xaee20230, 0x8ee20230,
+0x8c8b0008, 0x318200ff, 0x14400065, 0x0, 0x3c020001, 0x571021,
+0x904283b0, 0x14400060, 0x0, 0x8f8400e4, 0xc41023, 0x218c3,
+0x4620001, 0x24630200, 0x8f8900c4, 0x10600005, 0x24020001, 0x10620009,
+0x0, 0x8004177, 0x0, 0x8ee20220, 0x1205821, 0x24420001,
+0xaee20220, 0x80041ac, 0x8ee20220, 0x8ee20224, 0x3c05000a, 0x24420001,
+0xaee20224, 0x8c8b0000, 0x34a5f000, 0x8ee20224, 0x12b1823, 0xa3102b,
+0x54400001, 0x651821, 0x2c62233f, 0x14400040, 0x0, 0x8f8200e8,
+0x24420008, 0xaf8200e8, 0x8f8200e8, 0x8f8200e4, 0x1205821, 0x24420008,
+0xaf8200e4, 0x80041ac, 0x8f8200e4, 0x8ee20228, 0x3c03000a, 0x24420001,
+0xaee20228, 0x8c840000, 0x3463f000, 0x8ee20228, 0x883823, 0x67102b,
+0x54400001, 0xe33821, 0x3c020003, 0x34420d40, 0x47102b, 0x10400003,
+0x0, 0x80041ac, 0x805821, 0x8f8200e4, 0x24440008, 0xaf8400e4,
+0x8f8400e4, 0x10860018, 0x3c05000a, 0x34a5f000, 0x3c0a0003, 0x354a0d40,
+0x8ee2007c, 0x24420001, 0xaee2007c, 0x8c830000, 0x8ee2007c, 0x683823,
+0xa7102b, 0x54400001, 0xe53821, 0x147102b, 0x54400007, 0x605821,
+0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4, 0x1486ffef, 0x0,
+0x14860005, 0x0, 0x1205821, 0xaf8600e4, 0x80041ac, 0xaf8600e8,
+0xaf8400e4, 0xaf8400e8, 0x8f8200c8, 0x3c03000a, 0x3463f000, 0x483823,
+0x67102b, 0x54400001, 0xe33821, 0x3c020003, 0x34420d3f, 0x47102b,
+0x54400007, 0x6021, 0x1683823, 0x67102b, 0x54400003, 0xe33821,
+0x80041bf, 0x3c020003, 0x3c020003, 0x34420d3f, 0x47102b, 0x14400016,
+0x318200ff, 0x14400006, 0x0, 0x3c020001, 0x571021, 0x904283b0,
+0x1040000f, 0x0, 0x8ee2022c, 0x3c04fdff, 0x8ee30000, 0x3484ffff,
+0x24420001, 0xaee2022c, 0x8ee2022c, 0x24020001, 0x641824, 0x3c010001,
+0x370821, 0xa02283a8, 0x800421c, 0xaee30000, 0xaf8b00c8, 0x8f8300c8,
+0x8f8200c4, 0x3c04000a, 0x3484f000, 0x623823, 0x87102b, 0x54400001,
+0xe43821, 0x3c020003, 0x34420d40, 0x47102b, 0x2ce30001, 0x431025,
+0x10400008, 0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
+0x3c034000, 0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a,
+0x0, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8,
+0xaf8200e0, 0x3c020001, 0x8c427140, 0x3c030008, 0x8f8600e0, 0x431024,
+0x1040001d, 0x0, 0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000,
+0x3c0c0080, 0x24850008, 0x27622800, 0x50a20001, 0x27651800, 0x8c880004,
+0x8c820000, 0x8ca90000, 0x3103ffff, 0x431021, 0x4d1024, 0x24430010,
+0x6b102b, 0x54400001, 0x6a1821, 0x12b102b, 0x54400001, 0x12a4821,
+0x10690002, 0x10c1025, 0xac820004, 0xa02021, 0x14c4ffeb, 0x24850008,
+0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420002, 0xaf820220,
+0x8f830054, 0x8f820054, 0x8004227, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb,
+0x431024, 0xaf820220, 0x6010055, 0x0, 0x8ee20218, 0x24420001,
+0xaee20218, 0x8ee20218, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024,
+0x34420004, 0xaf820220, 0x8f830054, 0x8f820054, 0x8004241, 0x24630002,
+0x8f820054, 0x621023, 0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0,
0x30c20007, 0x10400012, 0x0, 0x8f8300e4, 0x2402fff8, 0xc21024,
-0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440050,
-0x8f820054, 0x821023, 0x2c420051, 0x10400004, 0x0, 0x8f8200e0,
+0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440032,
+0x8f820054, 0x821023, 0x2c420033, 0x10400004, 0x0, 0x8f8200e0,
0x10c2fff9, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffd, 0x431024,
0xaf820220, 0x8f8600e0, 0x30c20007, 0x10400003, 0x2402fff8, 0xc23024,
-0xaf8600e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 0x24680008, 0x48102b,
-0x10400003, 0x3c02fff5, 0x34421000, 0x1024021, 0x8f8b00c8, 0x8f850120,
-0x8f840124, 0x8004091, 0x6021, 0x27623800, 0x82102b, 0x50400001,
-0x27643000, 0x10a40010, 0x318200ff, 0x8c820018, 0x38430007, 0x2c630001,
-0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 0x24840020, 0x8ee20230,
-0x240c0001, 0x24420001, 0xaee20230, 0x8ee20230, 0x8c8b0008, 0x318200ff,
-0x14400065, 0x0, 0x3c020001, 0x571021, 0x904283b0, 0x14400060,
-0x0, 0x8f8400e4, 0xc41023, 0x218c3, 0x4620001, 0x24630200,
-0x8f8900c4, 0x10600005, 0x24020001, 0x10620009, 0x0, 0x80040d3,
-0x0, 0x8ee20220, 0x1205821, 0x24420001, 0xaee20220, 0x8004108,
-0x8ee20220, 0x8ee20224, 0x3c05000a, 0x24420001, 0xaee20224, 0x8c8b0000,
-0x34a5f000, 0x8ee20224, 0x12b1823, 0xa3102b, 0x54400001, 0x651821,
-0x2c62233f, 0x14400040, 0x0, 0x8f8200e8, 0x24420008, 0xaf8200e8,
-0x8f8200e8, 0x8f8200e4, 0x1205821, 0x24420008, 0xaf8200e4, 0x8004108,
-0x8f8200e4, 0x8ee20228, 0x3c03000a, 0x24420001, 0xaee20228, 0x8c840000,
-0x3463f000, 0x8ee20228, 0x883823, 0x67102b, 0x54400001, 0xe33821,
-0x3c020003, 0x34420d40, 0x47102b, 0x10400003, 0x0, 0x8004108,
-0x805821, 0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4, 0x10860018,
-0x3c05000a, 0x34a5f000, 0x3c0a0003, 0x354a0d40, 0x8ee2007c, 0x24420001,
-0xaee2007c, 0x8c830000, 0x8ee2007c, 0x683823, 0xa7102b, 0x54400001,
-0xe53821, 0x147102b, 0x54400007, 0x605821, 0x8f8200e4, 0x24440008,
-0xaf8400e4, 0x8f8400e4, 0x1486ffef, 0x0, 0x14860005, 0x0,
-0x1205821, 0xaf8600e4, 0x8004108, 0xaf8600e8, 0xaf8400e4, 0xaf8400e8,
-0x8f8200c8, 0x3c03000a, 0x3463f000, 0x483823, 0x67102b, 0x54400001,
-0xe33821, 0x3c020003, 0x34420d3f, 0x47102b, 0x54400007, 0x6021,
-0x1683823, 0x67102b, 0x54400003, 0xe33821, 0x800411b, 0x3c020003,
-0x3c020003, 0x34420d3f, 0x47102b, 0x14400016, 0x318200ff, 0x14400006,
-0x0, 0x3c020001, 0x571021, 0x904283b0, 0x1040000f, 0x0,
-0x8ee2022c, 0x3c04fdff, 0x8ee30000, 0x3484ffff, 0x24420001, 0xaee2022c,
-0x8ee2022c, 0x24020001, 0x641824, 0x3c010001, 0x370821, 0xa02283a8,
-0x8004178, 0xaee30000, 0xaf8b00c8, 0x8f8300c8, 0x8f8200c4, 0x3c04000a,
-0x3484f000, 0x623823, 0x87102b, 0x54400001, 0xe43821, 0x3c020003,
-0x34420d40, 0x47102b, 0x2ce30001, 0x431025, 0x10400008, 0x0,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x3c034000, 0x431025,
-0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, 0x0, 0x8ee2007c,
-0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0, 0x3c020001,
-0x8c426f30, 0x3c030008, 0x8f8600e0, 0x431024, 0x1040001d, 0x0,
-0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080, 0x24850008,
-0x27622800, 0x50a20001, 0x27651800, 0x8c880004, 0x8c820000, 0x8ca90000,
-0x3103ffff, 0x431021, 0x4d1024, 0x24430010, 0x6b102b, 0x54400001,
-0x6a1821, 0x12b102b, 0x54400001, 0x12a4821, 0x10690002, 0x10c1025,
-0xac820004, 0xa02021, 0x14c4ffeb, 0x24850008, 0x8f820220, 0x3c0308ff,
-0x3463ffff, 0x431024, 0x34420002, 0xaf820220, 0x8f830054, 0x8f820054,
-0x8004183, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220,
-0x6010055, 0x0, 0x8ee20218, 0x24420001, 0xaee20218, 0x8ee20218,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, 0xaf820220,
-0x8f830054, 0x8f820054, 0x800419d, 0x24630002, 0x8f820054, 0x621023,
-0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x30c20007, 0x10400012,
-0x0, 0x8f8300e4, 0x2402fff8, 0xc21024, 0x1043000d, 0x0,
-0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440032, 0x8f820054, 0x821023,
-0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x10c2fff9, 0x0,
-0x8f820220, 0x3c0308ff, 0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0,
-0x30c20007, 0x10400003, 0x2402fff8, 0xc23024, 0xaf8600e0, 0x240301f5,
-0x8f8200e8, 0x673823, 0x718c0, 0x431021, 0xaf8200e8, 0x8f8200e8,
-0xaf8200e4, 0x8ee2007c, 0x3c0408ff, 0x3484ffff, 0x471021, 0xaee2007c,
-0x8f820220, 0x3c038000, 0x34630002, 0x441024, 0x431025, 0xaf820220,
-0x8f830054, 0x8f820054, 0x80041d9, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb,
-0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008,
-0x27bd0028, 0x3c020001, 0x8c424dfc, 0x27bdffd8, 0x10400012, 0xafbf0020,
-0x3c040001, 0x24844b74, 0x3c050008, 0x24020001, 0x3c010001, 0x370821,
-0xac22839c, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50498, 0x3c010001,
-0xac204dfc, 0x3c010001, 0xac224df0, 0xc0023a7, 0x3821, 0x8f420268,
-0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, 0x8ee204c0, 0x8ee404c4,
-0x2403fffe, 0x431024, 0x30840002, 0x10800118, 0xaee204c0, 0x8ee204c4,
-0x2403fffd, 0x431024, 0xaee204c4, 0x8f820044, 0x3c030600, 0x34632000,
-0x34420020, 0xaf820044, 0xafa30018, 0x8ee205f8, 0x8f430228, 0x24420001,
-0x304a00ff, 0x514300f8, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021,
-0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008,
-0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800,
-0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007,
-0x1021, 0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x8004286,
-0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434,
-0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004,
-0x8ee205f8, 0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc,
-0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10,
-0x14400033, 0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021,
-0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b,
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20,
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005,
-0x0, 0x8004273, 0x0, 0x14600005, 0x0, 0x8f820128,
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010,
-0xac800000, 0x8004286, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003,
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0,
-0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54a00006, 0x240b0001,
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff,
-0x24020001, 0x54620076, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054,
-0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008,
-0x240c0011, 0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800,
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007,
-0x0, 0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x80042ef,
-0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c,
-0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4,
-0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24050001, 0x8ee24e20,
-0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0,
-0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001,
-0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0,
-0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80042dc, 0x0,
-0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128,
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80042ef, 0x0,
-0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001,
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000,
-0xac8a0004, 0x54a00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033,
-0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 0x54620003, 0xafa00010,
-0x800431c, 0x0, 0x3c040001, 0x24844b80, 0xafa00014, 0x8f860120,
-0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f011, 0x800431c, 0x0,
-0x3c040001, 0x24844b8c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
-0xc0023a7, 0x34a5f010, 0x800431c, 0x0, 0x3c040001, 0x24844b98,
-0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f,
-0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001,
-0xaee20158, 0x8ee20158, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c020001,
-0x8c424dfc, 0x27bdffe0, 0x1440000d, 0xafbf0018, 0x3c040001, 0x24844ba4,
-0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, 0x24020001,
-0x3c010001, 0xac224dfc, 0xc0023a7, 0x3821, 0x8ee204c0, 0x3c030001,
-0x771821, 0x946383a2, 0x34420001, 0x10600007, 0xaee204c0, 0x8f820220,
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24040001,
-0xc004f33, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3c120001, 0x26520f00, 0x3c140001, 0x8e944d70,
-0x3c100001, 0x26100e20, 0x3c15c000, 0x36b50060, 0x8e8a0000, 0x8eb30000,
-0x26a400b, 0x248000a, 0x200f821, 0x0, 0xd, 0x0,
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0xaf8600e0, 0x240301f5, 0x8f8200e8, 0x673823, 0x718c0, 0x431021,
+0xaf8200e8, 0x8f8200e8, 0xaf8200e4, 0x8ee2007c, 0x3c0408ff, 0x3484ffff,
+0x471021, 0xaee2007c, 0x8f820220, 0x3c038000, 0x34630002, 0x441024,
+0x431025, 0xaf820220, 0x8f830054, 0x8f820054, 0x800427d, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820220,
+0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c,
+0x8fb00018, 0x3e00008, 0x27bd0028, 0x3c020001, 0x8c42500c, 0x27bdffd8,
+0x10400012, 0xafbf0020, 0x3c040001, 0x24844d84, 0x3c050008, 0x24020001,
+0x3c010001, 0x370821, 0xac22839c, 0xafa00010, 0xafa00014, 0x8f860220,
+0x34a50498, 0x3c010001, 0xac20500c, 0x3c010001, 0xac225000, 0xc002403,
+0x3821, 0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268,
+0x8ee204c0, 0x8ee404c4, 0x2403fffe, 0x431024, 0x30840002, 0x1080011e,
+0xaee204c0, 0x8ee204c4, 0x2403fffd, 0x431024, 0xaee204c4, 0x8f820044,
+0x3c030600, 0x34632000, 0x34420020, 0xaf820044, 0xafa30018, 0x8ee205f8,
+0x8f430228, 0x24420001, 0x304a00ff, 0x514300fe, 0xafa00010, 0x8ee205f8,
+0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600,
+0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a,
+0x5821, 0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001,
+0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000,
+0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021,
+0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x800432d, 0x8ee201a0,
+0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821,
+0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8,
+0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021,
+0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033,
+0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
+0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
+0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
+0x800431a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
+0x800432d, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021,
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0xac8d0000, 0xac8e0004, 0x54a00006, 0x240b0001, 0x8f820054,
+0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001,
+0x54620079, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032,
+0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011,
+0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020,
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0,
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x2821, 0x24420001,
+0xaee201a0, 0x8004399, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490,
+0x8ee50494, 0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000,
+0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033,
+0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000,
+0x1448001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0,
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001,
+0x10470007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0,
+0x8004386, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020,
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000,
+0x8004399, 0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021,
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028,
+0x2e22021, 0xac880000, 0xac8a0004, 0x54a00006, 0x240b0001, 0x8f820054,
+0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001,
+0x54620003, 0xafa00010, 0x80043c6, 0x0, 0x3c040001, 0x24844d90,
+0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011,
+0x80043c6, 0x0, 0x3c040001, 0x24844d9c, 0xafa00014, 0x8f860120,
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80043c6, 0x0,
+0x3c040001, 0x24844da8, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009,
+0xc002403, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8,
+0x8ee20158, 0x24420001, 0xaee20158, 0x8ee20158, 0x8fbf0020, 0x3e00008,
+0x27bd0028, 0x3c020001, 0x8c42500c, 0x27bdffe0, 0x1440000d, 0xafbf0018,
+0x3c040001, 0x24844db4, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220,
+0x34a50499, 0x24020001, 0x3c010001, 0xac22500c, 0xc002403, 0x3821,
+0x8ee204c0, 0x3c030001, 0x771821, 0x946383a2, 0x34420001, 0x10600007,
+0xaee204c0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008,
+0xaf820220, 0x24040001, 0xc004fb3, 0x24050004, 0xaf420268, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x0, 0x0, 0x3c120001, 0x26521100,
+0x3c140001, 0x8e944f80, 0x3c100001, 0x26101020, 0x3c15c000, 0x36b50060,
+0x8e8a0000, 0x8eb30000, 0x26a400b, 0x248000a, 0x200f821, 0x0,
+0xd, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x80014c4, 0x0, 0x80014c6, 0x3c0a0001, 0x80014c6, 0x3c0a0002,
-0x80014c6, 0x0, 0x800244a, 0x0, 0x80014c6, 0x3c0a0003,
-0x80014c6, 0x3c0a0004, 0x8002ef8, 0x0, 0x80014c6, 0x3c0a0005,
-0x8003c3d, 0x0, 0x8003bbe, 0x0, 0x80014c6, 0x3c0a0006,
-0x80014c6, 0x3c0a0007, 0x80014c6, 0x0, 0x80014c6, 0x0,
-0x80014c6, 0x0, 0x80029f8, 0x0, 0x80014c6, 0x3c0a000b,
-0x80014c6, 0x3c0a000c, 0x80014c6, 0x3c0a000d, 0x800231c, 0x0,
-0x80022d9, 0x0, 0x80014c6, 0x3c0a000e, 0x8001b08, 0x0,
-0x8002448, 0x0, 0x80014c6, 0x3c0a000f, 0x8003ff3, 0x0,
-0x8003fdd, 0x0, 0x80014c6, 0x3c0a0010, 0x80014da, 0x0,
-0x80014c6, 0x3c0a0011, 0x80014c6, 0x3c0a0012, 0x80014c6, 0x3c0a0013,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+0x0, 0x0, 0x80014d6, 0x0, 0x80014d8, 0x3c0a0001,
+0x80014d8, 0x3c0a0002, 0x80014d8, 0x0, 0x80024a6, 0x0,
+0x80014d8, 0x3c0a0003, 0x80014d8, 0x3c0a0004, 0x8002f7c, 0x0,
+0x80014d8, 0x3c0a0005, 0x8003cd8, 0x0, 0x8003c56, 0x0,
+0x80014d8, 0x3c0a0006, 0x80014d8, 0x3c0a0007, 0x80014d8, 0x0,
+0x80014d8, 0x0, 0x80014d8, 0x0, 0x8002a75, 0x0,
+0x80014d8, 0x3c0a000b, 0x80014d8, 0x3c0a000c, 0x80014d8, 0x3c0a000d,
+0x8002378, 0x0, 0x8002335, 0x0, 0x80014d8, 0x3c0a000e,
+0x8001b38, 0x0, 0x80024a4, 0x0, 0x80014d8, 0x3c0a000f,
+0x8004097, 0x0, 0x8004081, 0x0, 0x80014d8, 0x3c0a0010,
+0x80014ee, 0x0, 0x80014d8, 0x3c0a0011, 0x80014d8, 0x3c0a0012,
+0x80014d8, 0x3c0a0013, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -2243,541 +2264,542 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x0, 0x0, 0x3c030001, 0x34633800, 0x24050080, 0x2404001f,
-0x2406ffff, 0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 0x3631021,
-0xaf8200c0, 0x3631021, 0xaf8200c4, 0x3631021, 0xaf8200c8, 0x27623800,
-0xaf8200d0, 0x27623800, 0xaf8200d4, 0x27623800, 0xaf8200d8, 0x27621800,
-0xaf8200e0, 0x27621800, 0xaf8200e4, 0x27621800, 0xaf8200e8, 0x27621000,
-0xaf8200f0, 0x27621000, 0xaf8200f4, 0x27621000, 0xaf8200f8, 0xaca00000,
-0x2484ffff, 0x1486fffd, 0x24a50004, 0x8f830040, 0x3c02f000, 0x621824,
-0x3c025000, 0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000,
-0x10620008, 0x24020800, 0x8004479, 0x0, 0x10620004, 0x24020800,
-0x8004479, 0x0, 0x24020700, 0x3c010001, 0xac224e00, 0x3e00008,
-0x0, 0x27bdffd0, 0xafbf0028, 0x3c010001, 0xc004b65, 0xac204de8,
-0x24040001, 0x2821, 0x27a60020, 0x34028000, 0xc004782, 0xa7a20020,
-0x8f830054, 0x8f820054, 0x800448b, 0x24630064, 0x8f820054, 0x621023,
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004740, 0x27a60020,
-0x8f830054, 0x8f820054, 0x8004497, 0x24630064, 0x8f820054, 0x621023,
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004740, 0x27a60020,
-0x8f830054, 0x8f820054, 0x80044a3, 0x24630064, 0x8f820054, 0x621023,
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 0xc004740, 0x27a60018,
-0x8f830054, 0x8f820054, 0x80044af, 0x24630064, 0x8f820054, 0x621023,
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 0xc004740, 0x27a6001a,
-0x97a20020, 0x10400022, 0x24030001, 0x3c020001, 0x8c424de8, 0x97a30018,
-0x34420001, 0x3c010001, 0xac224de8, 0x24020015, 0x14620008, 0x3402f423,
-0x97a3001a, 0x14620005, 0x24020003, 0x3c010001, 0xac224e9c, 0x80044e2,
-0x3c08fff0, 0x97a30018, 0x24027810, 0x1462000a, 0x24020002, 0x97a3001a,
-0x24020001, 0x14620006, 0x24020002, 0x24020004, 0x3c010001, 0xac224e9c,
-0x80044e2, 0x3c08fff0, 0x3c010001, 0xac224e9c, 0x80044e2, 0x3c08fff0,
-0x3c020001, 0x8c424de8, 0x3c010001, 0xac234e9c, 0x34420004, 0x3c010001,
-0xac224de8, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001,
-0x8ce74e9c, 0x3c040001, 0x24844c10, 0x24020001, 0x3c010001, 0xac224df0,
-0xafa60010, 0x3c060001, 0x8cc64de8, 0x97a2001a, 0x3c05000d, 0x34a50100,
-0x3c010001, 0xac204dec, 0x681821, 0x3c010001, 0xac234e94, 0xc0023a7,
-0xafa20014, 0x8fbf0028, 0x3e00008, 0x27bd0030, 0x27bdffe8, 0x24070004,
-0x3c040001, 0x8c844dec, 0x3021, 0x24020001, 0x1482000a, 0xafbf0010,
-0x3c020001, 0x8c426f3c, 0x3c050004, 0x30428000, 0x1040000c, 0x34a593e0,
-0x3c05000f, 0x8004515, 0x34a54240, 0x3c020001, 0x8c426f3c, 0x3c05000f,
-0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480, 0x3c020001,
-0x8c424e94, 0x8f830054, 0x451021, 0x431023, 0x45102b, 0x1440002e,
-0x0, 0x3c020001, 0x8c424df4, 0x1440002a, 0x2cc20001, 0x7182b,
-0x431024, 0x1040001d, 0x0, 0x3c090001, 0x8d294de8, 0x240b0001,
-0x3c054000, 0x3c080001, 0x25086f3c, 0x250afffc, 0x42042, 0x14800002,
-0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 0x2cc20001, 0x148b0004,
-0x0, 0x8d020000, 0x800453a, 0x451024, 0x8d420000, 0x451024,
-0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 0x431024, 0x5440ffed,
-0x42042, 0x3c010001, 0x10c00024, 0xac244dec, 0x8f830054, 0x24020001,
-0x3c010001, 0xac224df0, 0x3c010001, 0xac234e94, 0x3c020001, 0x8c424df0,
-0x10400006, 0x24020001, 0x3c010001, 0xac204df0, 0x3c010001, 0x370821,
-0xac22839c, 0x3c030001, 0x771821, 0x8c63839c, 0x24020008, 0x10620005,
-0x24020001, 0xc00456a, 0x0, 0x8004567, 0x0, 0x3c030001,
-0x8c634dec, 0x10620007, 0x2402000e, 0x3c030001, 0x8c636eb0, 0x10620003,
-0x0, 0xc004b88, 0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, 0x3c050001, 0x8ca54dec,
-0x3c040001, 0x8c844e04, 0x3442ffff, 0x621824, 0x14a40008, 0xaee30000,
-0x3c030001, 0x771821, 0x8c63839c, 0x3c020001, 0x8c424e08, 0x10620008,
-0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x3c010001, 0xac254e04,
-0x3c010001, 0xac224e08, 0x3c030001, 0x8c634dec, 0x24020002, 0x10620126,
-0x2c620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x80046ae,
-0x0, 0x24020004, 0x1062007c, 0x24020001, 0x80046af, 0x0,
-0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 0x2c620008, 0x10400117,
-0x31080, 0x3c010001, 0x220821, 0x8c224c28, 0x400008, 0x0,
-0xc0046b4, 0x0, 0x3c020001, 0x8c424df8, 0x3c010001, 0xac204d80,
-0x104000c5, 0x24020002, 0x3c010001, 0x370821, 0xac22839c, 0x3c010001,
-0x80046b1, 0xac204df8, 0xc0047c3, 0x0, 0x3c030001, 0x8c634e10,
-0x24020011, 0x146200fd, 0x24020003, 0x8004631, 0x0, 0x3c050001,
-0x8ca54dec, 0x3c060001, 0x8cc66f3c, 0xc004e2c, 0x24040001, 0x24020005,
-0x3c010001, 0xac204df8, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c,
-0x3c040001, 0x24844c1c, 0x3c05000f, 0x34a50100, 0x3021, 0x3821,
-0xafa00010, 0xc0023a7, 0xafa00014, 0x80046b1, 0x0, 0x8f820220,
-0x3c03f700, 0x431025, 0x8004658, 0xaf820220, 0x8f820220, 0x3c030004,
-0x431024, 0x14400095, 0x24020007, 0x8f830054, 0x3c020001, 0x8c424e90,
-0x2463d8f0, 0x431023, 0x2c422710, 0x144000d1, 0x24020001, 0x80046af,
-0x0, 0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 0xc004ff8,
-0x24040001, 0x3c030001, 0x8c636f34, 0x46100c3, 0x24020001, 0x3c020008,
-0x621024, 0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 0x431024,
-0x80045fa, 0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f,
-0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, 0x8f820220,
-0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220,
-0x24020008, 0x3c010001, 0x370821, 0xc004323, 0xac22839c, 0x80046b1,
-0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 0x2c620008,
-0x1040009e, 0x31080, 0x3c010001, 0x220821, 0x8c224c48, 0x400008,
-0x0, 0xc0041e7, 0x0, 0x3c010001, 0xac204df0, 0xaf800204,
-0x3c010001, 0xc0046b4, 0xac206f00, 0x8f820044, 0x34428080, 0xaf820044,
-0x8f830054, 0x3c010001, 0xac204d80, 0x800465a, 0x24020002, 0x8f830054,
-0x3c020001, 0x8c424e90, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400081,
-0x24020003, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 0x3c020001,
-0x8c426f38, 0x30424000, 0x10400005, 0x0, 0x8f820044, 0x3c03ffff,
-0x8004640, 0x34637fff, 0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044,
-0x8f830054, 0x800465a, 0x24020004, 0x8f830054, 0x3c020001, 0x8c424e90,
-0x2463d8f0, 0x431023, 0x2c422710, 0x14400065, 0x24020005, 0x3c010001,
-0x370821, 0x80046b1, 0xac22839c, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0xaf800204, 0x3c010001, 0xac206f00, 0x8f830054, 0x24020006,
-0x3c010001, 0x370821, 0xac22839c, 0x3c010001, 0x80046b1, 0xac234e90,
-0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, 0x3c030001, 0x8c634e90,
-0x3484869f, 0x451021, 0x621823, 0x83202b, 0x10800046, 0x0,
-0x24020007, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 0x8f820220,
-0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 0x3c030300, 0x431024,
-0x14400005, 0x1821, 0x8f820220, 0x24030001, 0x441025, 0xaf820220,
-0x10600030, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c844e88,
-0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x3c010001, 0x370821,
-0xac22839c, 0x10800007, 0x24020001, 0x3c010001, 0xac226eb0, 0xc004b88,
-0x8f840220, 0x80046b1, 0x0, 0x8f820220, 0x3c030008, 0x431024,
-0x1440001a, 0x2402000e, 0x3c010001, 0xac226eb0, 0x8ee20000, 0x24040001,
-0x3c030200, 0x431025, 0xc004ff8, 0xaee20000, 0x8f820220, 0x2403fffb,
-0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xc004323, 0xaf820220,
-0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 0x80046b1, 0x0,
-0x24020001, 0x3c010001, 0xac224df0, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820200,
-0x3c060001, 0x8cc64dec, 0x34420004, 0xaf820200, 0x24020002, 0x10c20048,
-0x2cc20003, 0x10400005, 0x24020001, 0x10c20008, 0x0, 0x8004708,
-0x0, 0x24020004, 0x10c20013, 0x24020001, 0x8004708, 0x0,
-0x3c030001, 0x8c634dd8, 0x3c020001, 0x8c424de4, 0x3c040001, 0x8c844e00,
-0x3c050001, 0x8ca54ddc, 0xaf860200, 0xaf860220, 0x34630022, 0x441025,
-0x451025, 0x34420002, 0x8004707, 0xaf830200, 0xaf820200, 0xaf820220,
-0x8f820044, 0x3c030001, 0x8c634e88, 0x34428080, 0xaf820044, 0x10600005,
-0x3c033f00, 0x3c020001, 0x8c424dd0, 0x80046fb, 0x346300e0, 0x8f8400f0,
-0x276217f8, 0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, 0x10a20007,
-0x3c038000, 0x34630040, 0x3c020001, 0x24424d90, 0xac820000, 0xac830004,
-0xaf8500f0, 0x3c020001, 0x8c424dd0, 0x3c033f00, 0x346300e2, 0x431025,
-0xaf820200, 0x3c030001, 0x8c634dd4, 0x3c04f700, 0x3c020001, 0x8c424de4,
-0x3c050001, 0x8ca54e00, 0x641825, 0x431025, 0x451025, 0xaf820220,
-0x3e00008, 0x0, 0x8f820220, 0x3c030001, 0x8c634dec, 0x34420004,
-0xaf820220, 0x24020001, 0x1062000f, 0x0, 0x8f830054, 0x8f820054,
-0x24630002, 0x621023, 0x2c420003, 0x10400011, 0x0, 0x8f820054,
-0x621023, 0x2c420003, 0x1040000c, 0x0, 0x8004719, 0x0,
-0x8f830054, 0x8f820054, 0x8004725, 0x24630007, 0x8f820054, 0x621023,
-0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0, 0x30820007, 0x1040000d,
-0x0, 0x8f820054, 0x8f8300e0, 0x14830009, 0x24450032, 0x8f820054,
-0xa21023, 0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x1082fff9,
-0x0, 0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, 0x3e00008,
-0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c,
-0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, 0xafbf0020,
-0xa6200000, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x2021, 0x24100010, 0x2501024, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x2501024,
-0x24100010, 0x2701024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fffa, 0x2701024, 0xc004b65, 0x34108000, 0xc004b65,
-0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65,
-0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
-0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018,
-0xa09021, 0xafb3001c, 0xc09821, 0xafb00010, 0x8021, 0xafbf0020,
-0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0,
-0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021,
-0xc004b3f, 0x24040001, 0x24100010, 0x2301024, 0x10400002, 0x2021,
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x2301024, 0x24100010,
-0x2501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042,
-0x1600fffa, 0x2501024, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021,
-0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, 0x24040001,
-0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0,
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008,
-0x27bd0028, 0x3c030001, 0x8c634e10, 0x3c020001, 0x8c424e54, 0x27bdffd8,
-0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001, 0xac234e54,
-0x2463ffff, 0x2c620013, 0x10400349, 0x31080, 0x3c010001, 0x220821,
-0x8c224c70, 0x400008, 0x0, 0xc004b65, 0x8021, 0x34028000,
-0xa7a20010, 0x27b10010, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001,
-0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0xc004b3f, 0x2021, 0x108042, 0x1600fffc,
-0x0, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8004b18,
-0x24020002, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021,
-0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021,
-0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004b3f, 0x2021,
-0x108042, 0x1600fffc, 0x0, 0xc004b65, 0x34108000, 0xc004b65,
-0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65,
-0x0, 0x97a20010, 0x30428000, 0x144002dc, 0x24020003, 0x8004b18,
-0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, 0xc004b3f,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f,
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f,
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004b3f,
-0x2021, 0x108042, 0x1600fffc, 0x0, 0xc004b3f, 0x24040001,
-0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0,
-0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x24020004, 0x8f830054,
-0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e,
-0x24020002, 0x3c030001, 0x8c634e9c, 0x10620297, 0x2c620003, 0x14400296,
-0x24020011, 0x24020003, 0x10620005, 0x24020004, 0x10620291, 0x2402000f,
-0x8004b18, 0x24020011, 0x8004b18, 0x24020005, 0x24020014, 0xa7a20010,
-0x27b10010, 0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020,
-0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001,
-0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa,
-0x32020001, 0x24100010, 0x32020012, 0x10400002, 0x2021, 0x24040001,
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020012, 0xc004b3f, 0x24040001,
-0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0,
-0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x24020006, 0x8f830054,
-0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400250,
-0x24020007, 0x8004b18, 0x0, 0x24020006, 0xa7a20010, 0x27b10010,
-0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f,
-0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fffa, 0x32020013, 0xc004b3f, 0x24040001, 0xc004b3f,
+0x0, 0x0, 0x0, 0x0, 0x3c030001, 0x34633800,
+0x24050080, 0x2404001f, 0x2406ffff, 0x24020001, 0xaf80021c, 0xaf820200,
+0xaf820220, 0x3631021, 0xaf8200c0, 0x3631021, 0xaf8200c4, 0x3631021,
+0xaf8200c8, 0x27623800, 0xaf8200d0, 0x27623800, 0xaf8200d4, 0x27623800,
+0xaf8200d8, 0x27621800, 0xaf8200e0, 0x27621800, 0xaf8200e4, 0x27621800,
+0xaf8200e8, 0x27621000, 0xaf8200f0, 0x27621000, 0xaf8200f4, 0x27621000,
+0xaf8200f8, 0xaca00000, 0x2484ffff, 0x1486fffd, 0x24a50004, 0x8f830040,
+0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 0x43102b, 0x14400006,
+0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x80044f9, 0x0,
+0x10620004, 0x24020800, 0x80044f9, 0x0, 0x24020700, 0x3c010001,
+0xac225010, 0x3e00008, 0x0, 0x27bdffd0, 0xafbf0028, 0x3c010001,
+0xc004be5, 0xac204ff8, 0x24040001, 0x2821, 0x27a60020, 0x34028000,
+0xc004802, 0xa7a20020, 0x8f830054, 0x8f820054, 0x800450b, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001,
+0xc0047c0, 0x27a60020, 0x8f830054, 0x8f820054, 0x8004517, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001,
+0xc0047c0, 0x27a60020, 0x8f830054, 0x8f820054, 0x8004523, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050002,
+0xc0047c0, 0x27a60018, 0x8f830054, 0x8f820054, 0x800452f, 0x24630064,
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050003,
+0xc0047c0, 0x27a6001a, 0x97a20020, 0x10400022, 0x24030001, 0x3c020001,
+0x8c424ff8, 0x97a30018, 0x34420001, 0x3c010001, 0xac224ff8, 0x24020015,
+0x14620008, 0x3402f423, 0x97a3001a, 0x14620005, 0x24020003, 0x3c010001,
+0xac2250ac, 0x8004562, 0x3c08fff0, 0x97a30018, 0x24027810, 0x1462000a,
+0x24020002, 0x97a3001a, 0x24020001, 0x14620006, 0x24020002, 0x24020004,
+0x3c010001, 0xac2250ac, 0x8004562, 0x3c08fff0, 0x3c010001, 0xac2250ac,
+0x8004562, 0x3c08fff0, 0x3c020001, 0x8c424ff8, 0x3c010001, 0xac2350ac,
+0x34420004, 0x3c010001, 0xac224ff8, 0x3c08fff0, 0x3508bdc0, 0x8f830054,
+0x97a60018, 0x3c070001, 0x8ce750ac, 0x3c040001, 0x24844e20, 0x24020001,
+0x3c010001, 0xac225000, 0xafa60010, 0x3c060001, 0x8cc64ff8, 0x97a2001a,
+0x3c05000d, 0x34a50100, 0x3c010001, 0xac204ffc, 0x681821, 0x3c010001,
+0xac2350a4, 0xc002403, 0xafa20014, 0x8fbf0028, 0x3e00008, 0x27bd0030,
+0x27bdffe8, 0x24070004, 0x3c040001, 0x8c844ffc, 0x3021, 0x24020001,
+0x1482000a, 0xafbf0010, 0x3c020001, 0x8c42714c, 0x3c050004, 0x30428000,
+0x1040000c, 0x34a593e0, 0x3c05000f, 0x8004595, 0x34a54240, 0x3c020001,
+0x8c42714c, 0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 0x3c05001e,
+0x34a58480, 0x3c020001, 0x8c4250a4, 0x8f830054, 0x451021, 0x431023,
+0x45102b, 0x1440002e, 0x0, 0x3c020001, 0x8c425004, 0x1440002a,
+0x2cc20001, 0x7182b, 0x431024, 0x1040001d, 0x0, 0x3c090001,
+0x8d294ff8, 0x240b0001, 0x3c054000, 0x3c080001, 0x2508714c, 0x250afffc,
+0x42042, 0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 0x5040000b,
+0x2cc20001, 0x148b0004, 0x0, 0x8d020000, 0x80045ba, 0x451024,
+0x8d420000, 0x451024, 0x54400001, 0x24060001, 0x2cc20001, 0x7182b,
+0x431024, 0x5440ffed, 0x42042, 0x3c010001, 0x10c00024, 0xac244ffc,
+0x8f830054, 0x24020001, 0x3c010001, 0xac225000, 0x3c010001, 0xac2350a4,
+0x3c020001, 0x8c425000, 0x10400006, 0x24020001, 0x3c010001, 0xac205000,
+0x3c010001, 0x370821, 0xac22839c, 0x3c030001, 0x771821, 0x8c63839c,
+0x24020008, 0x10620005, 0x24020001, 0xc0045ea, 0x0, 0x80045e7,
+0x0, 0x3c030001, 0x8c634ffc, 0x10620007, 0x2402000e, 0x3c030001,
+0x8c6370c0, 0x10620003, 0x0, 0xc004c08, 0x8f840220, 0x8fbf0010,
+0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000,
+0x3c050001, 0x8ca54ffc, 0x3c040001, 0x8c845014, 0x3442ffff, 0x621824,
+0x14a40008, 0xaee30000, 0x3c030001, 0x771821, 0x8c63839c, 0x3c020001,
+0x8c425018, 0x10620008, 0x0, 0x3c020001, 0x571021, 0x8c42839c,
+0x3c010001, 0xac255014, 0x3c010001, 0xac225018, 0x3c030001, 0x8c634ffc,
+0x24020002, 0x10620126, 0x2c620003, 0x10400005, 0x24020001, 0x10620008,
+0x0, 0x800472e, 0x0, 0x24020004, 0x1062007c, 0x24020001,
+0x800472f, 0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff,
+0x2c620008, 0x10400117, 0x31080, 0x3c010001, 0x220821, 0x8c224e38,
+0x400008, 0x0, 0xc004734, 0x0, 0x3c020001, 0x8c425008,
+0x3c010001, 0xac204f90, 0x104000c5, 0x24020002, 0x3c010001, 0x370821,
+0xac22839c, 0x3c010001, 0x8004731, 0xac205008, 0xc004843, 0x0,
+0x3c030001, 0x8c635020, 0x24020011, 0x146200fd, 0x24020003, 0x80046b1,
+0x0, 0x3c050001, 0x8ca54ffc, 0x3c060001, 0x8cc6714c, 0xc004eac,
+0x24040001, 0x24020005, 0x3c010001, 0xac205008, 0x3c010001, 0x370821,
+0x8004731, 0xac22839c, 0x3c040001, 0x24844e2c, 0x3c05000f, 0x34a50100,
+0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x8004731,
+0x0, 0x8f820220, 0x3c03f700, 0x431025, 0x80046d8, 0xaf820220,
+0x8f820220, 0x3c030004, 0x431024, 0x14400095, 0x24020007, 0x8f830054,
+0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000d1,
+0x24020001, 0x800472f, 0x0, 0x3c050001, 0x8ca54ffc, 0xc004fb3,
+0x24040001, 0xc005078, 0x24040001, 0x3c030001, 0x8c637144, 0x46100c3,
+0x24020001, 0x3c020008, 0x621024, 0x10400006, 0x0, 0x8f820214,
+0x3c03ffff, 0x431024, 0x800467a, 0x3442251f, 0x8f820214, 0x3c03ffff,
+0x431024, 0x3442241f, 0xaf820214, 0x8ee20000, 0x3c030200, 0x431025,
+0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220,
+0x34420002, 0xaf820220, 0x24020008, 0x3c010001, 0x370821, 0xc0043cd,
+0xac22839c, 0x8004731, 0x0, 0x3c020001, 0x571021, 0x8c42839c,
+0x2443ffff, 0x2c620008, 0x1040009e, 0x31080, 0x3c010001, 0x220821,
+0x8c224e58, 0x400008, 0x0, 0xc00428b, 0x0, 0x3c010001,
+0xac205000, 0xaf800204, 0x3c010001, 0xc004734, 0xac207110, 0x8f820044,
+0x34428080, 0xaf820044, 0x8f830054, 0x3c010001, 0xac204f90, 0x80046da,
+0x24020002, 0x8f830054, 0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023,
+0x2c422710, 0x14400081, 0x24020003, 0x3c010001, 0x370821, 0x8004731,
+0xac22839c, 0x3c020001, 0x8c427148, 0x30424000, 0x10400005, 0x0,
+0x8f820044, 0x3c03ffff, 0x80046c0, 0x34637fff, 0x8f820044, 0x2403ff7f,
+0x431024, 0xaf820044, 0x8f830054, 0x80046da, 0x24020004, 0x8f830054,
+0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400065,
+0x24020005, 0x3c010001, 0x370821, 0x8004731, 0xac22839c, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, 0x3c010001, 0xac207110,
+0x8f830054, 0x24020006, 0x3c010001, 0x370821, 0xac22839c, 0x3c010001,
+0x8004731, 0xac2350a0, 0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054,
+0x3c030001, 0x8c6350a0, 0x3484869f, 0x451021, 0x621823, 0x83202b,
+0x10800046, 0x0, 0x24020007, 0x3c010001, 0x370821, 0x8004731,
+0xac22839c, 0x8f820220, 0x3c04f700, 0x441025, 0xaf820220, 0x8f820220,
+0x3c030300, 0x431024, 0x14400005, 0x1821, 0x8f820220, 0x24030001,
+0x441025, 0xaf820220, 0x10600030, 0x24020001, 0x8f820214, 0x3c03ffff,
+0x3c040001, 0x8c845098, 0x431024, 0x3442251f, 0xaf820214, 0x24020008,
+0x3c010001, 0x370821, 0xac22839c, 0x10800007, 0x24020001, 0x3c010001,
+0xac2270c0, 0xc004c08, 0x8f840220, 0x8004731, 0x0, 0x8f820220,
+0x3c030008, 0x431024, 0x1440001a, 0x2402000e, 0x3c010001, 0xac2270c0,
+0x8ee20000, 0x24040001, 0x3c030200, 0x431025, 0xc005078, 0xaee20000,
+0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002,
+0xc0043cd, 0xaf820220, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 0x24040001,
+0x8004731, 0x0, 0x24020001, 0x3c010001, 0xac225000, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 0x34420004,
+0xaf820220, 0x8f820200, 0x3c060001, 0x8cc64ffc, 0x34420004, 0xaf820200,
+0x24020002, 0x10c20048, 0x2cc20003, 0x10400005, 0x24020001, 0x10c20008,
+0x0, 0x8004788, 0x0, 0x24020004, 0x10c20013, 0x24020001,
+0x8004788, 0x0, 0x3c030001, 0x8c634fe8, 0x3c020001, 0x8c424ff4,
+0x3c040001, 0x8c845010, 0x3c050001, 0x8ca54fec, 0xaf860200, 0xaf860220,
+0x34630022, 0x441025, 0x451025, 0x34420002, 0x8004787, 0xaf830200,
+0xaf820200, 0xaf820220, 0x8f820044, 0x3c030001, 0x8c635098, 0x34428080,
+0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 0x8c424fe0, 0x800477b,
+0x346300e0, 0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, 0x27651000,
+0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, 0x24424fa0,
+0xac820000, 0xac830004, 0xaf8500f0, 0x3c020001, 0x8c424fe0, 0x3c033f00,
+0x346300e2, 0x431025, 0xaf820200, 0x3c030001, 0x8c634fe4, 0x3c04f700,
+0x3c020001, 0x8c424ff4, 0x3c050001, 0x8ca55010, 0x641825, 0x431025,
+0x451025, 0xaf820220, 0x3e00008, 0x0, 0x8f820220, 0x3c030001,
+0x8c634ffc, 0x34420004, 0xaf820220, 0x24020001, 0x1062000f, 0x0,
+0x8f830054, 0x8f820054, 0x24630002, 0x621023, 0x2c420003, 0x10400011,
+0x0, 0x8f820054, 0x621023, 0x2c420003, 0x1040000c, 0x0,
+0x8004799, 0x0, 0x8f830054, 0x8f820054, 0x80047a5, 0x24630007,
+0x8f820054, 0x621023, 0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0,
+0x30820007, 0x1040000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14830009,
+0x24450032, 0x8f820054, 0xa21023, 0x2c420033, 0x10400004, 0x0,
+0x8f8200e0, 0x1082fff9, 0x0, 0x8f820220, 0x2403fffd, 0x431024,
+0xaf820220, 0x3e00008, 0x0, 0x0, 0x27bdffd8, 0xafb20018,
+0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010,
+0x8021, 0xafbf0020, 0xa6200000, 0xc004bbf, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010,
+0x2501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, 0x2021,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x2701024, 0xc004be5,
+0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005,
+0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004be5, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014,
+0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, 0xafb00010,
+0x8021, 0xafbf0020, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020,
+0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001,
+0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x2301024,
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa,
+0x2301024, 0x24100010, 0x2501024, 0x10400002, 0x2021, 0x24040001,
+0xc004bbf, 0x108042, 0x1600fffa, 0x2501024, 0xc004bbf, 0x24040001,
+0xc004bbf, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002,
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0,
+0xc004be5, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
+0x8fb00010, 0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635020, 0x3c020001,
+0x8c425064, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018,
+0x3c010001, 0xac235064, 0x2463ffff, 0x2c620013, 0x10400349, 0x31080,
+0x3c010001, 0x220821, 0x8c224e80, 0x400008, 0x0, 0xc004be5,
+0x8021, 0x34028000, 0xa7a20010, 0x27b10010, 0xc004bbf, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021,
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001,
+0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004bbf, 0x2021,
+0x108042, 0x1600fffc, 0x0, 0xc004bbf, 0x24040001, 0xc004bbf,
0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65,
-0x0, 0x8f830054, 0x8004b0a, 0x24020008, 0x8f830054, 0x3c020001,
-0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440020f, 0x24020009,
-0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f,
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f,
-0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa,
-0x32020018, 0xc004b65, 0x34108000, 0xc004b65, 0x0, 0xc004b1f,
-0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000,
-0x108042, 0x1600fff7, 0x0, 0xc004b65, 0x8021, 0x97a20010,
-0x27b10010, 0x34420001, 0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021,
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020018, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8,
-0x0, 0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x2402000a,
-0x8f830054, 0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064,
-0x1440019b, 0x2402000b, 0x8004b18, 0x0, 0x27b10010, 0xa7a00010,
-0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x2021, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fffa, 0x32020017, 0xc004b65, 0x34108000, 0xc004b65,
-0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000,
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65,
-0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, 0xc004b3f,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f,
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5,
+0x0, 0x8004b98, 0x24020002, 0x27b10010, 0xa7a00010, 0x8021,
+0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x24040001,
+0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0xc004bbf, 0x2021, 0x108042, 0x1600fffc, 0x0, 0xc004be5,
+0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005,
+0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7,
+0x0, 0xc004be5, 0x0, 0x97a20010, 0x30428000, 0x144002dc,
+0x24020003, 0x8004b98, 0x0, 0x24021200, 0xa7a20010, 0x27b10010,
+0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf,
+0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0xc004bbf, 0x2021, 0x108042, 0x1600fffc, 0x0,
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000,
+0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a,
+0x24020004, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 0x8c6350ac, 0x10620297,
+0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004,
+0x10620291, 0x2402000f, 0x8004b98, 0x24020011, 0x8004b98, 0x24020005,
+0x24020014, 0xa7a20010, 0x27b10010, 0x8021, 0xc004bbf, 0x24040001,
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021,
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001,
+0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, 0x10400002,
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020012,
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000,
+0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a,
+0x24020006, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400250, 0x24020007, 0x8004b98, 0x0, 0x24020006,
+0xa7a20010, 0x27b10010, 0x8021, 0xc004bbf, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020013, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8,
+0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 0x24020008,
+0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064,
+0x1440020f, 0x24020009, 0x8004b98, 0x0, 0x27b10010, 0xa7a00010,
+0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fffa, 0x32020018, 0xc004be5, 0x34108000, 0xc004be5,
+0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004be5,
+0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, 0xc004bbf,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf,
+0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf,
0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa,
-0x32020017, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000,
-0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8f830054,
-0x8004b0a, 0x2402000c, 0x8f830054, 0x3c020001, 0x8c424e98, 0x2463ff9c,
-0x431023, 0x2c420064, 0x14400127, 0x24020012, 0x8004b18, 0x0,
-0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021,
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020014, 0xc004b65,
-0x34108000, 0xc004b65, 0x0, 0xc004b1f, 0x0, 0x50400005,
+0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018,
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa,
+0x32020018, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000,
+0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054,
+0x8004b8a, 0x2402000a, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c,
+0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x8004b98, 0x0,
+0x27b10010, 0xa7a00010, 0x8021, 0xc004bbf, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020017, 0xc004be5,
+0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005,
0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7,
-0x0, 0xc004b65, 0x8021, 0x97a20010, 0x27b10010, 0x34420010,
-0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f,
-0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001,
-0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fffa, 0x32020014, 0xc004b3f, 0x24040001, 0xc004b3f,
+0x0, 0xc004be5, 0x8021, 0x97a20010, 0x27b10010, 0x34420700,
+0xa7a20010, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf,
+0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fffa, 0x32020017, 0xc004bbf, 0x24040001, 0xc004bbf,
0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021,
-0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65,
-0x0, 0x8f830054, 0x8004b0a, 0x24020013, 0x8f830054, 0x3c020001,
-0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x144000b3, 0x2402000d,
-0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f,
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f,
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5,
+0x0, 0x8f830054, 0x8004b8a, 0x2402000c, 0x8f830054, 0x3c020001,
+0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012,
+0x8004b98, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004bbf,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf,
+0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf,
0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001,
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa,
-0x32020018, 0xc004b65, 0x34108000, 0xc004b65, 0x0, 0xc004b1f,
+0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014,
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa,
+0x32020014, 0xc004be5, 0x34108000, 0xc004be5, 0x0, 0xc004b9f,
0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000,
-0x108042, 0x1600fff7, 0x0, 0xc004b65, 0x8021, 0x97a20010,
-0x27b10010, 0x3042fffe, 0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001,
-0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010,
-0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042,
-0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021,
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020018, 0xc004b3f,
-0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024,
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8,
-0x0, 0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x2402000e,
-0x24020840, 0xa7a20010, 0x27b10010, 0x8021, 0xc004b3f, 0x24040001,
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021,
-0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001,
-0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f,
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002,
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020013,
-0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000,
-0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042,
-0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8f830054, 0x24020010,
-0x3c010001, 0xac224e10, 0x3c010001, 0x8004b1a, 0xac234e98, 0x8f830054,
-0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004,
-0x0, 0x24020011, 0x3c010001, 0xac224e10, 0x8fbf0020, 0x8fb1001c,
-0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001,
-0x431025, 0x3c030008, 0xaf820044, 0x8f840054, 0x8f820054, 0xa32824,
-0x8004b2b, 0x24840001, 0x8f820054, 0x821023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f830054, 0x8f820054, 0x8004b39, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0xa01021, 0x8f830044,
-0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 0x3c020002, 0x822025,
-0x641825, 0xaf830044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044,
-0x8f830054, 0x8f820054, 0x8004b51, 0x24630001, 0x8f820054, 0x621023,
+0x108042, 0x1600fff7, 0x0, 0xc004be5, 0x8021, 0x97a20010,
+0x27b10010, 0x34420010, 0xa7a20010, 0xc004bbf, 0x24040001, 0x26100001,
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010,
+0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020014, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024,
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8,
+0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 0x24020013,
+0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064,
+0x144000b3, 0x2402000d, 0x8004b98, 0x0, 0x27b10010, 0xa7a00010,
+0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb,
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf,
+0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002,
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001,
+0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fffa, 0x32020018, 0xc004be5, 0x34108000, 0xc004be5,
+0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000,
+0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004be5,
+0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, 0xc004bbf,
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf,
+0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf,
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001,
+0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018,
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa,
+0x32020018, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000,
+0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf,
+0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054,
+0x8004b8a, 0x2402000e, 0x24020840, 0xa7a20010, 0x27b10010, 0x8021,
+0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0,
+0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021,
+0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021,
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010,
+0x32020013, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042,
+0x1600fffa, 0x32020013, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021,
+0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001,
+0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0,
+0x8f830054, 0x24020010, 0x3c010001, 0xac225020, 0x3c010001, 0x8004b9a,
+0xac2350a8, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, 0xac225020,
+0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044,
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, 0x8f840054,
+0x8f820054, 0xa32824, 0x8004bab, 0x24840001, 0x8f820054, 0x821023,
0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff,
-0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004b5f, 0x24630001,
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004bb9, 0x24630001,
0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
-0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054,
-0x8004b73, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f830054, 0x8f820054, 0x8004b81, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x0,
-0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, 0x8c63839c, 0x24020008,
-0x1462021c, 0x803021, 0x3c020001, 0x8c424e88, 0x14400033, 0x0,
-0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001, 0x621825,
-0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, 0x2c420001, 0x621825,
-0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001, 0x621825,
-0x10600005, 0x0, 0xc0041e7, 0x0, 0x8004bc1, 0x2402000e,
-0xc004323, 0x0, 0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001,
-0x3c030001, 0x8c634dec, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001,
-0x8c424de8, 0x8004bbd, 0x2403fff7, 0x3c020001, 0x8c424de8, 0x431024,
-0x3c010001, 0xac224de8, 0x2402000e, 0x3c010001, 0xc0041e7, 0xac226eb0,
-0x8004dab, 0x0, 0x8f820220, 0x3c030400, 0x431024, 0x10400027,
-0x2403ffbf, 0x8f850224, 0x3c020001, 0x8c426ebc, 0xa32024, 0x431024,
-0x1482000c, 0x0, 0x3c020001, 0x8c426ec0, 0x24420001, 0x3c010001,
-0xac226ec0, 0x2c420002, 0x14400008, 0x24020001, 0x3c010001, 0x8004be1,
-0xac226ee0, 0x3c010001, 0xac206ec0, 0x3c010001, 0xac206ee0, 0x3c020001,
-0x8c426ee0, 0x10400006, 0x30a20040, 0x10400004, 0x24020001, 0x3c010001,
-0x8004bec, 0xac226ee4, 0x3c010001, 0xac206ee4, 0x3c010001, 0xac256ebc,
-0x3c010001, 0x8004bfc, 0xac206ef0, 0x24020001, 0x3c010001, 0xac226ef0,
-0x3c010001, 0xac206ee0, 0x3c010001, 0xac206ec0, 0x3c010001, 0xac206ee4,
-0x3c010001, 0xac206ebc, 0x3c030001, 0x8c636eb0, 0x3c020001, 0x8c426eb4,
-0x10620003, 0x3c020200, 0x3c010001, 0xac236eb4, 0xc21024, 0x10400007,
-0x2463ffff, 0x8f820220, 0x24030001, 0x3c010001, 0xac234df0, 0x8004da9,
-0x3c03f700, 0x2c62000e, 0x10400198, 0x31080, 0x3c010001, 0x220821,
-0x8c224cc0, 0x400008, 0x0, 0x8ee20000, 0x3c03fdff, 0x3463ffff,
-0x431024, 0xaee20000, 0x3c010001, 0xac206ee0, 0x3c010001, 0xac206ec0,
-0x3c010001, 0xac206ef0, 0x3c010001, 0xac206ebc, 0x3c010001, 0xac206ee4,
-0x3c010001, 0xac206ed8, 0x3c010001, 0xac206ed0, 0xc00470a, 0xaf800224,
-0x24020002, 0x3c010001, 0xac226eb0, 0xc0041e7, 0x0, 0xaf800204,
-0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, 0xac206f00,
-0x8f830054, 0x3c020001, 0x8c426ed8, 0x24040001, 0x3c010001, 0xac246eec,
-0x24420001, 0x3c010001, 0xac226ed8, 0x2c420004, 0x3c010001, 0xac236ed4,
-0x14400006, 0x24020003, 0x3c010001, 0xac244df0, 0x3c010001, 0x8004da7,
-0xac206ed8, 0x3c010001, 0x8004da7, 0xac226eb0, 0x8f830054, 0x3c020001,
-0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400154, 0x24020004,
-0x3c010001, 0x8004da7, 0xac226eb0, 0x3c040001, 0x8c844e8c, 0x3c010001,
-0xc004dae, 0xac206ec8, 0x3c020001, 0x8c426efc, 0xaf820204, 0x8f820204,
-0x30420030, 0x1440013c, 0x24020002, 0x3c030001, 0x8c636efc, 0x24020005,
-0x3c010001, 0xac226eb0, 0x3c010001, 0x8004da7, 0xac236f00, 0x3c020001,
-0x8c426ee0, 0x10400139, 0x0, 0x3c020001, 0x8c426ebc, 0x10400135,
-0x0, 0x3c010001, 0xac226ee8, 0x24020003, 0x3c010001, 0xac226ec0,
-0x8004d3a, 0x24020006, 0x3c010001, 0xac206ec8, 0x8f820204, 0x34420040,
-0xaf820204, 0x3c020001, 0x8c426f00, 0x24030007, 0x3c010001, 0xac236eb0,
-0x34420040, 0x3c010001, 0xac226f00, 0x3c020001, 0x8c426ee0, 0x10400005,
-0x0, 0x3c020001, 0x8c426ebc, 0x10400110, 0x24020002, 0x3c050001,
-0x24a56ec0, 0x8ca20000, 0x2c424e21, 0x1040010a, 0x24020002, 0x3c020001,
-0x8c426ee4, 0x1040010f, 0x2404ffbf, 0x3c020001, 0x8c426ebc, 0x3c030001,
-0x8c636ee8, 0x441024, 0x641824, 0x14430007, 0x24020001, 0x24020003,
-0xaca20000, 0x24020008, 0x3c010001, 0x8004da7, 0xac226eb0, 0x3c010001,
-0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426eec, 0x1040000c, 0x24020001,
-0x3c040001, 0xc004dbb, 0x8c846ebc, 0x3c020001, 0x8c426f08, 0x14400005,
-0x24020001, 0x3c020001, 0x8c426f04, 0x10400006, 0x24020001, 0x3c010001,
-0xac224df0, 0x3c010001, 0x8004da7, 0xac206ed8, 0x8f820204, 0x34420040,
-0xaf820204, 0x3c020001, 0x8c426f00, 0x3c030001, 0x8c636ed0, 0x34420040,
-0x3c010001, 0xac226f00, 0x3c020001, 0x8c426ebc, 0x2c630001, 0x318c0,
-0x3c010001, 0xac236ed0, 0x30420008, 0x3c010001, 0xac226ecc, 0x8f830054,
-0x24020009, 0x3c010001, 0xac226eb0, 0x3c010001, 0x8004da7, 0xac236ed4,
-0x8f830054, 0x3c020001, 0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710,
-0x144000b6, 0x0, 0x3c020001, 0x8c426ee0, 0x10400005, 0x0,
-0x3c020001, 0x8c426ebc, 0x104000b7, 0x24020002, 0x3c030001, 0x24636ec0,
-0x8c620000, 0x2c424e21, 0x104000b1, 0x24020002, 0x3c020001, 0x8c426eec,
-0x1040000e, 0x0, 0x3c020001, 0x8c426ebc, 0x3c010001, 0xac206eec,
-0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, 0x1440000c,
-0x24020003, 0x8004d27, 0x2402000c, 0x3c020001, 0x8c426ebc, 0x30420080,
-0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003,
-0xac620000, 0x2402000a, 0x3c010001, 0xac226eb0, 0x3c040001, 0x24846ef8,
-0x8c820000, 0x3c030001, 0x8c636ed0, 0x431025, 0xaf820204, 0x8c830000,
-0x3c040001, 0x8c846ed0, 0x2402000b, 0x3c010001, 0xac226eb0, 0x641825,
-0x3c010001, 0xac236f00, 0x3c050001, 0x24a56ec0, 0x8ca20000, 0x2c424e21,
-0x1040007d, 0x24020002, 0x3c020001, 0x8c426ef0, 0x10400005, 0x0,
-0x2402000c, 0x3c010001, 0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426ee0,
-0x1040007a, 0x0, 0x3c040001, 0x8c846ebc, 0x1080006c, 0x30820008,
-0x3c030001, 0x8c636ecc, 0x10620072, 0x24020003, 0x3c010001, 0xac246ee8,
-0xaca20000, 0x24020006, 0x3c010001, 0x8004da7, 0xac226eb0, 0x8f8400f0,
-0x276217f8, 0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, 0x10a20007,
-0x3c038000, 0x34630040, 0x3c020001, 0x24424d90, 0xac820000, 0xac830004,
-0xaf8500f0, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d,
-0x3c010001, 0xac226eb0, 0x3c010001, 0xac236ed4, 0x8f830054, 0x3c020001,
-0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440003a, 0x0,
-0x3c020001, 0x8c426ef0, 0x10400029, 0x2402000e, 0x3c030001, 0x8c636f04,
-0x3c010001, 0x14600015, 0xac226eb0, 0xc004323, 0x0, 0x3c050001,
-0x8ca54dec, 0xc004f33, 0x24040001, 0x3c030001, 0x8c634dec, 0x24020004,
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c424de8, 0x8004d76, 0x2403fff7,
-0x3c020001, 0x8c424de8, 0x431024, 0x3c010001, 0xac224de8, 0x8ee20000,
-0x3c030200, 0x431025, 0xaee20000, 0x8f820224, 0x3c010001, 0xac226f0c,
-0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002,
-0x8004da7, 0xaf820220, 0x3c020001, 0x8c426ee0, 0x10400005, 0x0,
-0x3c020001, 0x8c426ebc, 0x1040000f, 0x24020002, 0x3c020001, 0x8c426ec0,
-0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, 0x8c426ee0, 0x1040000f,
-0x0, 0x3c020001, 0x8c426ebc, 0x1440000b, 0x0, 0x24020002,
-0x3c010001, 0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426ee0, 0x10400003,
-0x0, 0xc0041e7, 0x0, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030001, 0x24636f08,
-0x8c620000, 0x10400005, 0x34422000, 0x3c010001, 0xac226efc, 0x8004db9,
-0xac600000, 0x3c010001, 0xac246efc, 0x3e00008, 0x0, 0x27bdffe0,
-0x30820030, 0xafbf0018, 0x3c010001, 0xac226f04, 0x14400067, 0x3c02ffff,
-0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d,
-0x30838000, 0x31a02, 0x30820001, 0x21200, 0x3c040001, 0x8c844e8c,
-0x621825, 0x331c2, 0x3c030001, 0x24634e6c, 0x30828000, 0x21202,
-0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021,
-0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, 0x10600007,
-0x24020002, 0x10620013, 0x24020003, 0x1062002c, 0x3c05000f, 0x8004e1d,
-0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x3c010001, 0xac206f44,
-0x3c010001, 0x8004e28, 0xac206f4c, 0x8f820200, 0x34420100, 0xaf820200,
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x24020100,
-0x3c010001, 0xac226f44, 0x3c010001, 0x8004e28, 0xac206f4c, 0x8f820200,
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025,
-0xaf820220, 0x3c010001, 0xac206f44, 0x3c010001, 0x8004e28, 0xac236f4c,
-0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025,
-0xaf820220, 0x24020100, 0x3c010001, 0xac226f44, 0x3c010001, 0x8004e28,
-0xac236f4c, 0x34a5ffff, 0x3c040001, 0x24844cf8, 0xafa30010, 0xc0023a7,
-0xafa00014, 0x8004e28, 0x0, 0x24020030, 0x3c010001, 0xac226f08,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8, 0xafb10024,
-0x808821, 0xafb3002c, 0xa09821, 0xafb00020, 0xc08021, 0x3c040001,
-0x24844d10, 0x3c050009, 0x3c020001, 0x8c424dec, 0x34a59001, 0x2203021,
-0x2603821, 0xafbf0030, 0xafb20028, 0xa7a0001a, 0xafb00014, 0xc0023a7,
-0xafa20010, 0x24020002, 0x126200e9, 0x2e620003, 0x10400005, 0x24020001,
-0x1262000a, 0x3c02fffb, 0x8004f2c, 0x0, 0x24020004, 0x1262006d,
-0x24020008, 0x1262006c, 0x3c02ffec, 0x8004f2c, 0x0, 0x3442ffff,
-0x2028024, 0x119140, 0x3c010001, 0x320821, 0xac306f1c, 0x3c024000,
-0x2021024, 0x10400046, 0x1023c2, 0x30840030, 0x101382, 0x3042000c,
-0x3c030001, 0x24634e14, 0x431021, 0x823821, 0x3c020020, 0x2021024,
-0x10400006, 0x24020100, 0x3c010001, 0x320821, 0xac226f20, 0x8004e6f,
-0x3c020080, 0x3c010001, 0x320821, 0xac206f20, 0x3c020080, 0x2021024,
-0x10400006, 0x111940, 0x3c020001, 0x3c010001, 0x230821, 0x8004e7b,
-0xac226f28, 0x111140, 0x3c010001, 0x220821, 0xac206f28, 0x94e30000,
-0x32024000, 0x10400003, 0xa7a30018, 0x34624000, 0xa7a20018, 0x24040001,
-0x94e20002, 0x24050004, 0x24e60002, 0x34420001, 0xc004782, 0xa4e20002,
-0x24040001, 0x2821, 0xc004782, 0x27a60018, 0x3c020001, 0x8c424dec,
-0x24110001, 0x3c010001, 0xac314df8, 0x14530004, 0x32028000, 0xc0041e7,
-0x0, 0x32028000, 0x10400095, 0x0, 0xc0041e7, 0x0,
-0x24020002, 0x3c010001, 0xac314df0, 0x3c010001, 0x8004f2c, 0xac224dec,
-0x24040001, 0x24050004, 0x27b0001a, 0xc004782, 0x2003021, 0x24040001,
-0x2821, 0xc004782, 0x2003021, 0x3c020001, 0x521021, 0x8c426f14,
-0x3c040001, 0x8c844dec, 0x3c03bfff, 0x3463ffff, 0x3c010001, 0xac334df8,
-0x431024, 0x3c010001, 0x320821, 0x10930074, 0xac226f14, 0x8004f2c,
-0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025,
-0x111140, 0x3c010001, 0x220821, 0xac306f18, 0x3c022000, 0x2021024,
-0x10400005, 0x24020001, 0x3c010001, 0xac224e88, 0x8004ecd, 0x3c024000,
-0x3c010001, 0xac204e88, 0x3c024000, 0x2021024, 0x1440001c, 0x0,
-0x3c020001, 0x8c424e88, 0x10400007, 0x24022020, 0x3c010001, 0xac224e8c,
-0x24020001, 0x3c010001, 0x370821, 0xac22839c, 0x3c04bfff, 0x111940,
-0x3c020001, 0x431021, 0x8c426f10, 0x3c050001, 0x8ca54dec, 0x3484ffff,
-0x441024, 0x3c010001, 0x230821, 0xac226f10, 0x24020001, 0x10a20044,
-0x0, 0x8004f2a, 0x0, 0x3c020001, 0x8c424e88, 0x1040001c,
-0x24022000, 0x3c010001, 0xac224e8c, 0x3c0300a0, 0x2031024, 0x14430005,
-0x111140, 0x3402a000, 0x3c010001, 0x8004f25, 0xac224e8c, 0x3c030001,
-0x621821, 0x8c636f18, 0x3c020020, 0x621024, 0x10400004, 0x24022001,
-0x3c010001, 0x8004f25, 0xac224e8c, 0x3c020080, 0x621024, 0x1040001f,
-0x3402a001, 0x3c010001, 0x8004f25, 0xac224e8c, 0x3c020020, 0x2021024,
-0x10400007, 0x111940, 0x24020100, 0x3c010001, 0x230821, 0xac226f24,
-0x8004f19, 0x3c020080, 0x111140, 0x3c010001, 0x220821, 0xac206f24,
+0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824,
+0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c030001,
+0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004bd1, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054,
+0x8004bdf, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff,
+0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044,
+0x8f830054, 0x8f820054, 0x8004bf3, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004c01, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
+0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821,
+0x8c63839c, 0x24020008, 0x1462021c, 0x803021, 0x3c020001, 0x8c425098,
+0x14400033, 0x0, 0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010,
+0x2c420001, 0x621825, 0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400,
+0x2c420001, 0x621825, 0x14600007, 0x38a30402, 0x2c630001, 0x38a20404,
+0x2c420001, 0x621825, 0x10600005, 0x0, 0xc00428b, 0x0,
+0x8004c41, 0x2402000e, 0xc0043cd, 0x0, 0x3c050001, 0x8ca54ffc,
+0xc004fb3, 0x24040001, 0x3c030001, 0x8c634ffc, 0x24020004, 0x14620005,
+0x2403fffb, 0x3c020001, 0x8c424ff8, 0x8004c3d, 0x2403fff7, 0x3c020001,
+0x8c424ff8, 0x431024, 0x3c010001, 0xac224ff8, 0x2402000e, 0x3c010001,
+0xc00428b, 0xac2270c0, 0x8004e2b, 0x0, 0x8f820220, 0x3c030400,
+0x431024, 0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001, 0x8c4270cc,
+0xa32024, 0x431024, 0x1482000c, 0x0, 0x3c020001, 0x8c4270d0,
+0x24420001, 0x3c010001, 0xac2270d0, 0x2c420002, 0x14400008, 0x24020001,
+0x3c010001, 0x8004c61, 0xac2270f0, 0x3c010001, 0xac2070d0, 0x3c010001,
+0xac2070f0, 0x3c020001, 0x8c4270f0, 0x10400006, 0x30a20040, 0x10400004,
+0x24020001, 0x3c010001, 0x8004c6c, 0xac2270f4, 0x3c010001, 0xac2070f4,
+0x3c010001, 0xac2570cc, 0x3c010001, 0x8004c7c, 0xac207100, 0x24020001,
+0x3c010001, 0xac227100, 0x3c010001, 0xac2070f0, 0x3c010001, 0xac2070d0,
+0x3c010001, 0xac2070f4, 0x3c010001, 0xac2070cc, 0x3c030001, 0x8c6370c0,
+0x3c020001, 0x8c4270c4, 0x10620003, 0x3c020200, 0x3c010001, 0xac2370c4,
+0xc21024, 0x10400007, 0x2463ffff, 0x8f820220, 0x24030001, 0x3c010001,
+0xac235000, 0x8004e29, 0x3c03f700, 0x2c62000e, 0x10400198, 0x31080,
+0x3c010001, 0x220821, 0x8c224ed0, 0x400008, 0x0, 0x8ee20000,
+0x3c03fdff, 0x3463ffff, 0x431024, 0xaee20000, 0x3c010001, 0xac2070f0,
+0x3c010001, 0xac2070d0, 0x3c010001, 0xac207100, 0x3c010001, 0xac2070cc,
+0x3c010001, 0xac2070f4, 0x3c010001, 0xac2070e8, 0x3c010001, 0xac2070e0,
+0xc00478a, 0xaf800224, 0x24020002, 0x3c010001, 0xac2270c0, 0xc00428b,
+0x0, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200,
+0x3c010001, 0xac207110, 0x8f830054, 0x3c020001, 0x8c4270e8, 0x24040001,
+0x3c010001, 0xac2470fc, 0x24420001, 0x3c010001, 0xac2270e8, 0x2c420004,
+0x3c010001, 0xac2370e4, 0x14400006, 0x24020003, 0x3c010001, 0xac245000,
+0x3c010001, 0x8004e27, 0xac2070e8, 0x3c010001, 0x8004e27, 0xac2270c0,
+0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 0x431023, 0x2c422710,
+0x14400154, 0x24020004, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c040001,
+0x8c84509c, 0x3c010001, 0xc004e2e, 0xac2070d8, 0x3c020001, 0x8c42710c,
+0xaf820204, 0x8f820204, 0x30420030, 0x1440013c, 0x24020002, 0x3c030001,
+0x8c63710c, 0x24020005, 0x3c010001, 0xac2270c0, 0x3c010001, 0x8004e27,
+0xac237110, 0x3c020001, 0x8c4270f0, 0x10400139, 0x0, 0x3c020001,
+0x8c4270cc, 0x10400135, 0x0, 0x3c010001, 0xac2270f8, 0x24020003,
+0x3c010001, 0xac2270d0, 0x8004dba, 0x24020006, 0x3c010001, 0xac2070d8,
+0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c427110, 0x24030007,
+0x3c010001, 0xac2370c0, 0x34420040, 0x3c010001, 0xac227110, 0x3c020001,
+0x8c4270f0, 0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x10400110,
+0x24020002, 0x3c050001, 0x24a570d0, 0x8ca20000, 0x2c424e21, 0x1040010a,
+0x24020002, 0x3c020001, 0x8c4270f4, 0x1040010f, 0x2404ffbf, 0x3c020001,
+0x8c4270cc, 0x3c030001, 0x8c6370f8, 0x441024, 0x641824, 0x14430007,
+0x24020001, 0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 0x8004e27,
+0xac2270c0, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c020001, 0x8c4270fc,
+0x1040000c, 0x24020001, 0x3c040001, 0xc004e3b, 0x8c8470cc, 0x3c020001,
+0x8c427118, 0x14400005, 0x24020001, 0x3c020001, 0x8c427114, 0x10400006,
+0x24020001, 0x3c010001, 0xac225000, 0x3c010001, 0x8004e27, 0xac2070e8,
+0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c427110, 0x3c030001,
+0x8c6370e0, 0x34420040, 0x3c010001, 0xac227110, 0x3c020001, 0x8c4270cc,
+0x2c630001, 0x318c0, 0x3c010001, 0xac2370e0, 0x30420008, 0x3c010001,
+0xac2270dc, 0x8f830054, 0x24020009, 0x3c010001, 0xac2270c0, 0x3c010001,
+0x8004e27, 0xac2370e4, 0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0,
+0x431023, 0x2c422710, 0x144000b6, 0x0, 0x3c020001, 0x8c4270f0,
+0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x104000b7, 0x24020002,
+0x3c030001, 0x246370d0, 0x8c620000, 0x2c424e21, 0x104000b1, 0x24020002,
+0x3c020001, 0x8c4270fc, 0x1040000e, 0x0, 0x3c020001, 0x8c4270cc,
+0x3c010001, 0xac2070fc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204,
+0x30420080, 0x1440000c, 0x24020003, 0x8004da7, 0x2402000c, 0x3c020001,
+0x8c4270cc, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080,
+0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 0xac2270c0,
+0x3c040001, 0x24847108, 0x8c820000, 0x3c030001, 0x8c6370e0, 0x431025,
+0xaf820204, 0x8c830000, 0x3c040001, 0x8c8470e0, 0x2402000b, 0x3c010001,
+0xac2270c0, 0x641825, 0x3c010001, 0xac237110, 0x3c050001, 0x24a570d0,
+0x8ca20000, 0x2c424e21, 0x1040007d, 0x24020002, 0x3c020001, 0x8c427100,
+0x10400005, 0x0, 0x2402000c, 0x3c010001, 0x8004e27, 0xac2270c0,
+0x3c020001, 0x8c4270f0, 0x1040007a, 0x0, 0x3c040001, 0x8c8470cc,
+0x1080006c, 0x30820008, 0x3c030001, 0x8c6370dc, 0x10620072, 0x24020003,
+0x3c010001, 0xac2470f8, 0xaca20000, 0x24020006, 0x3c010001, 0x8004e27,
+0xac2270c0, 0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, 0x27651000,
+0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, 0x24424fa0,
+0xac820000, 0xac830004, 0xaf8500f0, 0x8f820200, 0x34420002, 0xaf820200,
+0x8f830054, 0x2402000d, 0x3c010001, 0xac2270c0, 0x3c010001, 0xac2370e4,
+0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 0x431023, 0x2c422710,
+0x1440003a, 0x0, 0x3c020001, 0x8c427100, 0x10400029, 0x2402000e,
+0x3c030001, 0x8c637114, 0x3c010001, 0x14600015, 0xac2270c0, 0xc0043cd,
+0x0, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 0x24040001, 0x3c030001,
+0x8c634ffc, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 0x8c424ff8,
+0x8004df6, 0x2403fff7, 0x3c020001, 0x8c424ff8, 0x431024, 0x3c010001,
+0xac224ff8, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, 0x8f820224,
+0x3c010001, 0xac22711c, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
+0x8f820220, 0x34420002, 0x8004e27, 0xaf820220, 0x3c020001, 0x8c4270f0,
+0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x1040000f, 0x24020002,
+0x3c020001, 0x8c4270d0, 0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001,
+0x8c4270f0, 0x1040000f, 0x0, 0x3c020001, 0x8c4270cc, 0x1440000b,
+0x0, 0x24020002, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c020001,
+0x8c4270f0, 0x10400003, 0x0, 0xc00428b, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x3c030001, 0x24637118, 0x8c620000, 0x10400005, 0x34422000, 0x3c010001,
+0xac22710c, 0x8004e39, 0xac600000, 0x3c010001, 0xac24710c, 0x3e00008,
+0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001, 0xac227114,
+0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030,
+0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200,
+0x3c040001, 0x8c84509c, 0x621825, 0x331c2, 0x3c030001, 0x2463507c,
+0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2,
+0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025,
+0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c,
+0x3c05000f, 0x8004e9d, 0x0, 0x8f820200, 0x2403feff, 0x431024,
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
+0x3c010001, 0xac207154, 0x3c010001, 0x8004ea8, 0xac20715c, 0x8f820200,
+0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820220, 0x24020100, 0x3c010001, 0xac227154, 0x3c010001, 0x8004ea8,
+0xac20715c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 0xac207154, 0x3c010001,
+0x8004ea8, 0xac23715c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, 0xac227154,
+0x3c010001, 0x8004ea8, 0xac23715c, 0x34a5ffff, 0x3c040001, 0x24844f08,
+0xafa30010, 0xc002403, 0xafa00014, 0x8004ea8, 0x0, 0x24020030,
+0x3c010001, 0xac227118, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0,
+0x27bdffc8, 0xafb10024, 0x808821, 0xafb3002c, 0xa09821, 0xafb00020,
+0xc08021, 0x3c040001, 0x24844f20, 0x3c050009, 0x3c020001, 0x8c424ffc,
+0x34a59001, 0x2203021, 0x2603821, 0xafbf0030, 0xafb20028, 0xa7a0001a,
+0xafb00014, 0xc002403, 0xafa20010, 0x24020002, 0x126200e9, 0x2e620003,
+0x10400005, 0x24020001, 0x1262000a, 0x3c02fffb, 0x8004fac, 0x0,
+0x24020004, 0x1262006d, 0x24020008, 0x1262006c, 0x3c02ffec, 0x8004fac,
+0x0, 0x3442ffff, 0x2028024, 0x119140, 0x3c010001, 0x320821,
+0xac30712c, 0x3c024000, 0x2021024, 0x10400046, 0x1023c2, 0x30840030,
+0x101382, 0x3042000c, 0x3c030001, 0x24635024, 0x431021, 0x823821,
+0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, 0x320821,
+0xac227130, 0x8004eef, 0x3c020080, 0x3c010001, 0x320821, 0xac207130,
0x3c020080, 0x2021024, 0x10400006, 0x111940, 0x3c020001, 0x3c010001,
-0x230821, 0x8004f25, 0xac226f2c, 0x111140, 0x3c010001, 0x220821,
-0xac206f2c, 0x3c030001, 0x8c634dec, 0x24020001, 0x10620003, 0x0,
-0xc0041e7, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024,
-0x8fb00020, 0x3e00008, 0x27bd0038, 0x27bdffd0, 0xafb40028, 0x80a021,
-0xafb20020, 0x9021, 0xafb30024, 0x9821, 0xafb1001c, 0x8821,
-0x24020002, 0xafbf002c, 0xafb00018, 0xa7a00012, 0x10a20068, 0xa7a00010,
-0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 0x148140, 0x8004ff0,
-0x2201021, 0x24020004, 0x10a2005e, 0x24020008, 0x10a2005d, 0x142140,
-0x8004ff0, 0x2201021, 0x3c030001, 0x701821, 0x8c636f1c, 0x3c024000,
-0x621024, 0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 0x628824,
-0x3c010001, 0x300821, 0xac316f14, 0x8004ff0, 0x2201021, 0x24050001,
-0xc004740, 0x27a60010, 0x24040001, 0x24050001, 0xc004740, 0x27a60010,
-0x97a20010, 0x30420004, 0x10400034, 0x3c114000, 0x3c030001, 0x8c634e9c,
-0x24020003, 0x10620008, 0x2c620004, 0x14400029, 0x3c028000, 0x24020004,
-0x10620014, 0x24040001, 0x8004f99, 0x3c028000, 0x24040001, 0x24050011,
-0x27b00012, 0xc004740, 0x2003021, 0x24040001, 0x24050011, 0xc004740,
-0x2003021, 0x97a30012, 0x30624000, 0x10400002, 0x3c130010, 0x3c130008,
-0x3c120001, 0x8004f96, 0x30628000, 0x24050014, 0x27b00012, 0xc004740,
-0x2003021, 0x24040001, 0x24050014, 0xc004740, 0x2003021, 0x97a30012,
-0x30621000, 0x10400002, 0x3c130010, 0x3c130008, 0x3c120001, 0x30620800,
-0x54400001, 0x3c120002, 0x3c028000, 0x2221025, 0x2531825, 0x8004fa3,
-0x438825, 0x3c110001, 0x2308821, 0x8e316f1c, 0x3c027fff, 0x3442ffff,
-0x2228824, 0x141140, 0x3c010001, 0x220821, 0xac316f14, 0x8004ff0,
-0x2201021, 0x142140, 0x3c030001, 0x641821, 0x8c636f18, 0x3c024000,
-0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001,
-0x240821, 0xac316f10, 0x8004ff0, 0x2201021, 0x3c020001, 0x8c424dfc,
-0x1040002d, 0x3c11c00c, 0x3c020001, 0x8c424e88, 0x3c03e00c, 0x3c010001,
-0x240821, 0x8c246f24, 0x2102b, 0x21023, 0x431024, 0x10800004,
-0x518825, 0x3c020020, 0x8004fcd, 0x2228825, 0x3c02ffdf, 0x3442ffff,
-0x2228824, 0x141140, 0x3c010001, 0x220821, 0x8c226f2c, 0x10400003,
-0x3c020080, 0x8004fd8, 0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824,
-0x3c020001, 0x8c424e60, 0x10400002, 0x3c020800, 0x2228825, 0x3c020001,
-0x8c424e64, 0x10400002, 0x3c020400, 0x2228825, 0x3c020001, 0x8c424e68,
-0x10400006, 0x3c020100, 0x8004feb, 0x2228825, 0x3c027fff, 0x3442ffff,
-0x628824, 0x141140, 0x3c010001, 0x220821, 0xac316f10, 0x2201021,
-0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018,
-0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb40020, 0x80a021, 0xafbf0024,
-0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f900200, 0x3c030001,
-0x8c634dec, 0x8f930220, 0x24020002, 0x106200b1, 0x2c620003, 0x10400005,
-0x24020001, 0x1062000a, 0x141940, 0x80050b7, 0x0, 0x24020004,
-0x1062005a, 0x24020008, 0x10620059, 0x149140, 0x80050b7, 0x0,
-0x3c040001, 0x832021, 0x8c846f1c, 0x3c110001, 0x2238821, 0x8e316f14,
-0x3c024000, 0x821024, 0x1040003e, 0x3c020008, 0x2221024, 0x10400020,
-0x36100002, 0x3c020001, 0x431021, 0x8c426f20, 0x10400005, 0x36100020,
-0x36100100, 0x3c020020, 0x800502f, 0x2228825, 0x2402feff, 0x2028024,
+0x230821, 0x8004efb, 0xac227138, 0x111140, 0x3c010001, 0x220821,
+0xac207138, 0x94e30000, 0x32024000, 0x10400003, 0xa7a30018, 0x34624000,
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 0x24e60002, 0x34420001,
+0xc004802, 0xa4e20002, 0x24040001, 0x2821, 0xc004802, 0x27a60018,
+0x3c020001, 0x8c424ffc, 0x24110001, 0x3c010001, 0xac315008, 0x14530004,
+0x32028000, 0xc00428b, 0x0, 0x32028000, 0x10400095, 0x0,
+0xc00428b, 0x0, 0x24020002, 0x3c010001, 0xac315000, 0x3c010001,
+0x8004fac, 0xac224ffc, 0x24040001, 0x24050004, 0x27b0001a, 0xc004802,
+0x2003021, 0x24040001, 0x2821, 0xc004802, 0x2003021, 0x3c020001,
+0x521021, 0x8c427124, 0x3c040001, 0x8c844ffc, 0x3c03bfff, 0x3463ffff,
+0x3c010001, 0xac335008, 0x431024, 0x3c010001, 0x320821, 0x10930074,
+0xac227124, 0x8004fac, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024,
+0x3c020008, 0x2028025, 0x111140, 0x3c010001, 0x220821, 0xac307128,
+0x3c022000, 0x2021024, 0x10400005, 0x24020001, 0x3c010001, 0xac225098,
+0x8004f4d, 0x3c024000, 0x3c010001, 0xac205098, 0x3c024000, 0x2021024,
+0x1440001c, 0x0, 0x3c020001, 0x8c425098, 0x10400007, 0x24022020,
+0x3c010001, 0xac22509c, 0x24020001, 0x3c010001, 0x370821, 0xac22839c,
+0x3c04bfff, 0x111940, 0x3c020001, 0x431021, 0x8c427120, 0x3c050001,
+0x8ca54ffc, 0x3484ffff, 0x441024, 0x3c010001, 0x230821, 0xac227120,
+0x24020001, 0x10a20044, 0x0, 0x8004faa, 0x0, 0x3c020001,
+0x8c425098, 0x1040001c, 0x24022000, 0x3c010001, 0xac22509c, 0x3c0300a0,
+0x2031024, 0x14430005, 0x111140, 0x3402a000, 0x3c010001, 0x8004fa5,
+0xac22509c, 0x3c030001, 0x621821, 0x8c637128, 0x3c020020, 0x621024,
+0x10400004, 0x24022001, 0x3c010001, 0x8004fa5, 0xac22509c, 0x3c020080,
+0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x8004fa5, 0xac22509c,
+0x3c020020, 0x2021024, 0x10400007, 0x111940, 0x24020100, 0x3c010001,
+0x230821, 0xac227134, 0x8004f99, 0x3c020080, 0x111140, 0x3c010001,
+0x220821, 0xac207134, 0x3c020080, 0x2021024, 0x10400006, 0x111940,
+0x3c020001, 0x3c010001, 0x230821, 0x8004fa5, 0xac22713c, 0x111140,
+0x3c010001, 0x220821, 0xac20713c, 0x3c030001, 0x8c634ffc, 0x24020001,
+0x10620003, 0x0, 0xc00428b, 0x0, 0x8fbf0030, 0x8fb3002c,
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0038, 0x27bdffd0,
+0xafb40028, 0x80a021, 0xafb20020, 0x9021, 0xafb30024, 0x9821,
+0xafb1001c, 0x8821, 0x24020002, 0xafbf002c, 0xafb00018, 0xa7a00012,
+0x10a20068, 0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a,
+0x148140, 0x8005070, 0x2201021, 0x24020004, 0x10a2005e, 0x24020008,
+0x10a2005d, 0x142140, 0x8005070, 0x2201021, 0x3c030001, 0x701821,
+0x8c63712c, 0x3c024000, 0x621024, 0x14400009, 0x24040001, 0x3c027fff,
+0x3442ffff, 0x628824, 0x3c010001, 0x300821, 0xac317124, 0x8005070,
+0x2201021, 0x24050001, 0xc0047c0, 0x27a60010, 0x24040001, 0x24050001,
+0xc0047c0, 0x27a60010, 0x97a20010, 0x30420004, 0x10400034, 0x3c114000,
+0x3c030001, 0x8c6350ac, 0x24020003, 0x10620008, 0x2c620004, 0x14400029,
+0x3c028000, 0x24020004, 0x10620014, 0x24040001, 0x8005019, 0x3c028000,
+0x24040001, 0x24050011, 0x27b00012, 0xc0047c0, 0x2003021, 0x24040001,
+0x24050011, 0xc0047c0, 0x2003021, 0x97a30012, 0x30624000, 0x10400002,
+0x3c130010, 0x3c130008, 0x3c120001, 0x8005016, 0x30628000, 0x24050014,
+0x27b00012, 0xc0047c0, 0x2003021, 0x24040001, 0x24050014, 0xc0047c0,
+0x2003021, 0x97a30012, 0x30621000, 0x10400002, 0x3c130010, 0x3c130008,
+0x3c120001, 0x30620800, 0x54400001, 0x3c120002, 0x3c028000, 0x2221025,
+0x2531825, 0x8005023, 0x438825, 0x3c110001, 0x2308821, 0x8e31712c,
+0x3c027fff, 0x3442ffff, 0x2228824, 0x141140, 0x3c010001, 0x220821,
+0xac317124, 0x8005070, 0x2201021, 0x142140, 0x3c030001, 0x641821,
+0x8c637128, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff,
+0x628824, 0x3c010001, 0x240821, 0xac317120, 0x8005070, 0x2201021,
+0x3c020001, 0x8c42500c, 0x1040002d, 0x3c11c00c, 0x3c020001, 0x8c425098,
+0x3c03e00c, 0x3c010001, 0x240821, 0x8c247134, 0x2102b, 0x21023,
+0x431024, 0x10800004, 0x518825, 0x3c020020, 0x800504d, 0x2228825,
0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, 0x3c010001, 0x220821,
-0x8c226f28, 0x10400005, 0x3c020001, 0x2629825, 0x3c020080, 0x800504e,
-0x2228825, 0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff7f, 0x3442ffff,
-0x800504e, 0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe, 0x3442ffff,
-0x2629824, 0x3c02ff5f, 0x3442ffff, 0x2228824, 0x3c010001, 0x230821,
-0xac206f20, 0x3c010001, 0x230821, 0xac206f28, 0xc00470a, 0x0,
-0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x34420002, 0xaf820220, 0x8005065, 0x141140, 0x8f820200,
-0x2403fffd, 0x431024, 0xc00470a, 0xaf820200, 0x3c02bfff, 0x3442ffff,
-0xc0041e7, 0x2228824, 0x141140, 0x3c010001, 0x220821, 0x80050b7,
-0xac316f14, 0x149140, 0x3c040001, 0x922021, 0x8c846f18, 0x3c110001,
-0x2328821, 0x8e316f10, 0x3c024000, 0x821024, 0x14400011, 0x0,
-0x3c020001, 0x8c424e88, 0x14400006, 0x3c02bfff, 0x8f820200, 0x34420002,
-0xc00470a, 0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc0041e7, 0x2228824,
-0x3c010001, 0x320821, 0x80050b7, 0xac316f10, 0x3c020001, 0x8c424e88,
-0x1440002d, 0x141140, 0x3c020020, 0x821024, 0x10400007, 0x36100020,
-0x24020100, 0x3c010001, 0x320821, 0xac226f24, 0x8005097, 0x36100100,
-0x3c010001, 0x320821, 0xac206f24, 0x2402feff, 0x2028024, 0x3c020080,
-0x821024, 0x10400007, 0x141940, 0x3c020001, 0x3c010001, 0x230821,
-0xac226f2c, 0x80050a8, 0x2629825, 0x141140, 0x3c010001, 0x220821,
-0xac206f2c, 0x3c02fffe, 0x3442ffff, 0x2629824, 0xc00470a, 0x0,
-0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220,
-0x8f820220, 0x34420002, 0xaf820220, 0x141140, 0x3c010001, 0x220821,
-0xac316f10, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014,
-0x8fb00010, 0x3e00008, 0x27bd0028, 0x0, 0x0 };
-u32 tigonFwData[(MAX_DATA_LEN/4) + 1] = {
+0x8c22713c, 0x10400003, 0x3c020080, 0x8005058, 0x2228825, 0x3c02ff7f,
+0x3442ffff, 0x2228824, 0x3c020001, 0x8c425070, 0x10400002, 0x3c020800,
+0x2228825, 0x3c020001, 0x8c425074, 0x10400002, 0x3c020400, 0x2228825,
+0x3c020001, 0x8c425078, 0x10400006, 0x3c020100, 0x800506b, 0x2228825,
+0x3c027fff, 0x3442ffff, 0x628824, 0x141140, 0x3c010001, 0x220821,
+0xac317120, 0x2201021, 0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020,
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb40020,
+0x80a021, 0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010,
+0x8f900200, 0x3c030001, 0x8c634ffc, 0x8f930220, 0x24020002, 0x106200b1,
+0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 0x141940, 0x8005137,
+0x0, 0x24020004, 0x1062005a, 0x24020008, 0x10620059, 0x149140,
+0x8005137, 0x0, 0x3c040001, 0x832021, 0x8c84712c, 0x3c110001,
+0x2238821, 0x8e317124, 0x3c024000, 0x821024, 0x1040003e, 0x3c020008,
+0x2221024, 0x10400020, 0x36100002, 0x3c020001, 0x431021, 0x8c427130,
+0x10400005, 0x36100020, 0x36100100, 0x3c020020, 0x80050af, 0x2228825,
+0x2402feff, 0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140,
+0x3c010001, 0x220821, 0x8c227138, 0x10400005, 0x3c020001, 0x2629825,
+0x3c020080, 0x80050ce, 0x2228825, 0x3c02fffe, 0x3442ffff, 0x2629824,
+0x3c02ff7f, 0x3442ffff, 0x80050ce, 0x2228824, 0x2402fedf, 0x2028024,
+0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff, 0x2228824,
+0x3c010001, 0x230821, 0xac207130, 0x3c010001, 0x230821, 0xac207138,
+0xc00478a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb,
+0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 0x80050e5,
+0x141140, 0x8f820200, 0x2403fffd, 0x431024, 0xc00478a, 0xaf820200,
+0x3c02bfff, 0x3442ffff, 0xc00428b, 0x2228824, 0x141140, 0x3c010001,
+0x220821, 0x8005137, 0xac317124, 0x149140, 0x3c040001, 0x922021,
+0x8c847128, 0x3c110001, 0x2328821, 0x8e317120, 0x3c024000, 0x821024,
+0x14400011, 0x0, 0x3c020001, 0x8c425098, 0x14400006, 0x3c02bfff,
+0x8f820200, 0x34420002, 0xc00478a, 0xaf820200, 0x3c02bfff, 0x3442ffff,
+0xc00428b, 0x2228824, 0x3c010001, 0x320821, 0x8005137, 0xac317120,
+0x3c020001, 0x8c425098, 0x1440002d, 0x141140, 0x3c020020, 0x821024,
+0x10400007, 0x36100020, 0x24020100, 0x3c010001, 0x320821, 0xac227134,
+0x8005117, 0x36100100, 0x3c010001, 0x320821, 0xac207134, 0x2402feff,
+0x2028024, 0x3c020080, 0x821024, 0x10400007, 0x141940, 0x3c020001,
+0x3c010001, 0x230821, 0xac22713c, 0x8005128, 0x2629825, 0x141140,
+0x3c010001, 0x220821, 0xac20713c, 0x3c02fffe, 0x3442ffff, 0x2629824,
+0xc00478a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb,
+0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 0x141140,
+0x3c010001, 0x220821, 0xac317120, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0,
+0x0 };
+u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041,
0x63654e49, 0x43205600, 0x42424242, 0x0, 0x0, 0x0,
0x135430, 0x13e7fc, 0x0, 0x0, 0x0, 0x0,
@@ -2792,7 +2814,7 @@ u32 tigonFwData[(MAX_DATA_LEN/4) + 1] = {
0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x30001, 0x1,
0x30201, 0x0, 0x0 };
-u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] = {
+u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f66, 0x776d6169,
0x6e2e632c, 0x7620312e, 0x312e322e, 0x31312031, 0x3939382f, 0x30342f32,
@@ -2813,114 +2835,114 @@ u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] = {
0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x0, 0x0,
0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f63, 0x6f6d6d61,
-0x6e642e63, 0x2c762031, 0x2e312e32, 0x2e382031, 0x3939382f, 0x30342f32,
-0x37203232, 0x3a31333a, 0x33392073, 0x6875616e, 0x67204578, 0x70202400,
-0x4e4f636f, 0x6d616e64, 0x0, 0x68737465, 0x5f455252, 0x0,
-0x412d4572, 0x72427563, 0x0, 0x4552524f, 0x522d4164, 0x64000000,
-0x656e714d, 0x45765046, 0x61696c00, 0x656e714d, 0x45764661, 0x696c0000,
-0x6661696c, 0x456e454d, 0x0, 0x442d4572, 0x724c6173, 0x74000000,
-0x442d4572, 0x72320000, 0x6d437374, 0x4d644552, 0x52000000, 0x70726f6d,
-0x4d644552, 0x52000000, 0x46696c74, 0x4d644552, 0x52000000, 0x636d645f,
-0x45525200, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0,
-0x6576526e, 0x6746756c, 0x6c000000, 0x0, 0x6da4, 0x7e7c,
-0x6d3c, 0x85c8, 0x815c, 0x8614, 0x8614, 0x6e58,
-0x7578, 0x7dcc, 0x7f68, 0x7f34, 0x8614, 0x7d30,
-0x7f8c, 0x6d68, 0x808c, 0x0, 0x24486561, 0x6465723a,
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
-0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6d612e63, 0x2c762031, 0x2e312e32,
-0x2e332031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x34312073,
-0x6875616e, 0x67204578, 0x70202400, 0x646d6172, 0x6441544e, 0x0,
-0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0,
-0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
-0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f74, 0x72616365,
-0x2e632c76, 0x20312e31, 0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720,
-0x32323a31, 0x333a3530, 0x20736875, 0x616e6720, 0x45787020, 0x24000000,
-0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
-0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6174612e,
-0x632c7620, 0x312e312e, 0x322e3220, 0x31393938, 0x2f30342f, 0x32372032,
-0x323a3133, 0x3a343020, 0x73687561, 0x6e672045, 0x78702024, 0x0,
-0x46575f56, 0x45525349, 0x4f4e3a20, 0x23312046, 0x7269204f, 0x63742031,
-0x36203130, 0x3a31333a, 0x30352050, 0x44542031, 0x39393800, 0x46575f43,
-0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031303a, 0x31333a30, 0x35000000,
-0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000,
-0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
-0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065,
-0x6e672e61, 0x6374656f, 0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049,
-0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, 0x20322e37, 0x2e320000,
+0x6e642e63, 0x2c762031, 0x2e312e31, 0x362e3120, 0x31393938, 0x2f31312f,
+0x31392030, 0x323a3339, 0x3a323520, 0x73687561, 0x6e672045, 0x78702024,
+0x0, 0x3f4d626f, 0x78457674, 0x0, 0x4e4f636f, 0x6d616e64,
+0x0, 0x68737465, 0x5f455252, 0x0, 0x412d4572, 0x72427563,
+0x0, 0x4552524f, 0x522d4164, 0x64000000, 0x656e714d, 0x45765046,
+0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 0x6661696c, 0x456e454d,
+0x0, 0x442d4572, 0x724c6173, 0x74000000, 0x442d4572, 0x72320000,
+0x6d437374, 0x4d644552, 0x52000000, 0x70726f6d, 0x4d644552, 0x52000000,
+0x46696c74, 0x4d644552, 0x52000000, 0x636d645f, 0x45525200, 0x3f456e71,
+0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6576526e, 0x6746756c,
+0x6c000000, 0x0, 0x6e90, 0x7fac, 0x6e28, 0x871c,
+0x8298, 0x8768, 0x8768, 0x6f44, 0x7684, 0x7efc,
+0x8098, 0x8064, 0x8768, 0x7e60, 0x80bc, 0x6e54,
+0x81bc, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d,
+0x6f6e2f64, 0x6d612e63, 0x2c762031, 0x2e312e32, 0x2e332031, 0x3939382f,
+0x30342f32, 0x37203232, 0x3a31333a, 0x34312073, 0x6875616e, 0x67204578,
+0x70202400, 0x646d6172, 0x6441544e, 0x0, 0x646d6177, 0x7241544e,
0x0, 0x0, 0x0, 0x0, 0x24486561, 0x6465723a,
0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
-0x2f66772f, 0x636f6d6d, 0x6f6e2f6d, 0x656d2e63, 0x2c762031, 0x2e312e32,
-0x2e322031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x34342073,
-0x6875616e, 0x67204578, 0x70202400, 0x0, 0x24486561, 0x6465723a,
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
-0x2f66772f, 0x636f6d6d, 0x6f6e2f73, 0x656e642e, 0x632c7620, 0x312e312e,
-0x322e3820, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343820,
-0x73687561, 0x6e672045, 0x78702024, 0x0, 0x736e6464, 0x654e6f51,
-0x20000000, 0x6e6f454e, 0x515f5458, 0x0, 0x736e6464, 0x744e6f51,
-0x20000000, 0x3f6e6f51, 0x64547845, 0x0, 0x756e6b72, 0x64747970,
-0x65000000, 0x0, 0xba70, 0xba70, 0xbb18, 0xac2c,
-0xae2c, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18,
-0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18,
-0xbb18, 0xbb18, 0xbb18, 0xae14, 0x24486561, 0x6465723a,
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
-0x2f66772f, 0x636f6d6d, 0x6f6e2f72, 0x6563762e, 0x632c7620, 0x312e312e,
-0x322e3139, 0x20313939, 0x382f3037, 0x2f323420, 0x32313a33, 0x303a3035,
-0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x706b5278, 0x45525200,
-0x66726d32, 0x4c617267, 0x65000000, 0x72784e6f, 0x52784264, 0x0,
-0x72785144, 0x6d614446, 0x0, 0x72785144, 0x6d614246, 0x0,
-0x3f6e6f51, 0x64527845, 0x0, 0x706b5278, 0x45525273, 0x0,
-0x66726d32, 0x4c726753, 0x0, 0x72784e6f, 0x42645300, 0x3f724264,
-0x446d6146, 0x0, 0x3f724a42, 0x64446d46, 0x0, 0x0,
-0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0,
-0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0,
-0xf3c0, 0xf3c0, 0xf3c0, 0xf3b8, 0xf3b8, 0xf3b8,
-0x572d444d, 0x41456e46, 0x0, 0x0, 0xfafc, 0xfe80,
-0xfb18, 0xfe80, 0xfe80, 0xfe80, 0xfe80, 0xfe80,
-0xfe80, 0xf44c, 0xfe80, 0xfe80, 0xfe80, 0xfe80,
-0xfe80, 0xfe78, 0xfe78, 0xfe78, 0x24486561, 0x6465723a,
+0x2f66772f, 0x636f6d6d, 0x6f6e2f74, 0x72616365, 0x2e632c76, 0x20312e31,
+0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 0x32323a31, 0x333a3530,
+0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x24486561, 0x6465723a,
0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
-0x2f66772f, 0x636f6d6d, 0x6f6e2f6d, 0x61632e63, 0x2c762031, 0x2e312e32,
-0x2e313220, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343220,
-0x73687561, 0x6e672045, 0x78702024, 0x0, 0x6d616374, 0x7841544e,
-0x0, 0x4e745379, 0x6e264c6b, 0x0, 0x72656d61, 0x73737274,
-0x0, 0x6c696e6b, 0x444f574e, 0x0, 0x656e714d, 0x45765046,
-0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 0x6661696c, 0x456e454d,
-0x0, 0x6c696e6b, 0x55500000, 0x0, 0x24486561, 0x6465723a,
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
-0x2f66772f, 0x636f6d6d, 0x6f6e2f63, 0x6b73756d, 0x2e632c76, 0x20312e31,
-0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 0x32323a31, 0x333a3339,
-0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x50726f62, 0x65506879,
-0x0, 0x6c6e6b41, 0x53535254, 0x0, 0x11680, 0x116b8,
-0x116dc, 0x11710, 0x1173c, 0x11750, 0x1178c, 0x11ac4,
-0x11864, 0x118a4, 0x118d4, 0x11914, 0x11944, 0x11980,
-0x119c4, 0x11ac4, 0x0, 0x0, 0x11f5c, 0x1202c,
-0x12104, 0x121d4, 0x12230, 0x1230c, 0x12334, 0x12410,
-0x12438, 0x125e0, 0x12608, 0x127b0, 0x129a8, 0x12c3c,
-0x12b50, 0x12c3c, 0x12c68, 0x127d8, 0x12980, 0x0,
-0x13054, 0x130b4, 0x13130, 0x1315c, 0x131ac, 0x131e8,
-0x1321c, 0x132a8, 0x13360, 0x13430, 0x13470, 0x134f4,
-0x13550, 0x13684, 0x646f4261, 0x73655067, 0x0, 0x0,
-0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, 0x0,
-0x0 };
+0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6174612e, 0x632c7620, 0x312e312e,
+0x322e3220, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343020,
+0x73687561, 0x6e672045, 0x78702024, 0x0, 0x46575f56, 0x45525349,
+0x4f4e3a20, 0x2331204d, 0x6f6e2044, 0x65632037, 0x2031343a, 0x35363a33,
+0x30205053, 0x54203139, 0x39380000, 0x46575f43, 0x4f4d5049, 0x4c455f54,
+0x494d453a, 0x2031343a, 0x35363a33, 0x30000000, 0x46575f43, 0x4f4d5049,
+0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049,
+0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 0x0, 0x46575f43,
+0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f,
+0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 0x4c45523a, 0x20676363,
+0x20766572, 0x73696f6e, 0x20322e37, 0x2e320000, 0x0, 0x0,
+0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d,
+0x6f6e2f6d, 0x656d2e63, 0x2c762031, 0x2e312e32, 0x2e322031, 0x3939382f,
+0x30342f32, 0x37203232, 0x3a31333a, 0x34342073, 0x6875616e, 0x67204578,
+0x70202400, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d,
+0x6f6e2f73, 0x656e642e, 0x632c7620, 0x312e312e, 0x322e3820, 0x31393938,
+0x2f30342f, 0x32372032, 0x323a3133, 0x3a343820, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x736e6464, 0x654e6f51, 0x20000000, 0x6e6f454e,
+0x515f5458, 0x0, 0x736e6464, 0x744e6f51, 0x20000000, 0x3f6e6f51,
+0x64547845, 0x0, 0x756e6b72, 0x64747970, 0x65000000, 0x0,
+0xbc88, 0xbc88, 0xbd30, 0xae2c, 0xb038, 0xbd30,
+0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30,
+0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30,
+0xbd30, 0xb020, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d,
+0x6f6e2f72, 0x6563762e, 0x632c7620, 0x312e312e, 0x322e3139, 0x20313939,
+0x382f3037, 0x2f323420, 0x32313a33, 0x303a3035, 0x20736875, 0x616e6720,
+0x45787020, 0x24000000, 0x706b5278, 0x45525200, 0x66726d32, 0x4c617267,
+0x65000000, 0x72784e6f, 0x52784264, 0x0, 0x72785144, 0x6d614446,
+0x0, 0x72785144, 0x6d614246, 0x0, 0x3f6e6f51, 0x64527845,
+0x0, 0x706b5278, 0x45525273, 0x0, 0x66726d32, 0x4c726753,
+0x0, 0x72784e6f, 0x42645300, 0x3f724264, 0x446d6146, 0x0,
+0x3f724a42, 0x64446d46, 0x0, 0x0, 0xf638, 0xf638,
+0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 0xf638,
+0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 0xf638,
+0xf638, 0xf630, 0xf630, 0xf630, 0x572d444d, 0x41456e46,
+0x0, 0x0, 0xfd80, 0x1011c, 0xfd9c, 0x1011c,
+0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x1011c, 0xf6c4,
+0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x10114,
+0x10114, 0x10114, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d,
+0x6f6e2f6d, 0x61632e63, 0x2c762031, 0x2e312e32, 0x2e313220, 0x31393938,
+0x2f30342f, 0x32372032, 0x323a3133, 0x3a343220, 0x73687561, 0x6e672045,
+0x78702024, 0x0, 0x6d616374, 0x7841544e, 0x0, 0x4e745379,
+0x6e264c6b, 0x0, 0x72656d61, 0x73737274, 0x0, 0x6c696e6b,
+0x444f574e, 0x0, 0x656e714d, 0x45765046, 0x61696c00, 0x656e714d,
+0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, 0x0, 0x6c696e6b,
+0x55500000, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d,
+0x6f6e2f63, 0x6b73756d, 0x2e632c76, 0x20312e31, 0x2e322e32, 0x20313939,
+0x382f3034, 0x2f323720, 0x32323a31, 0x333a3339, 0x20736875, 0x616e6720,
+0x45787020, 0x24000000, 0x50726f62, 0x65506879, 0x0, 0x6c6e6b41,
+0x53535254, 0x0, 0x11880, 0x118b8, 0x118dc, 0x11910,
+0x1193c, 0x11950, 0x1198c, 0x11cc4, 0x11a64, 0x11aa4,
+0x11ad4, 0x11b14, 0x11b44, 0x11b80, 0x11bc4, 0x11cc4,
+0x0, 0x0, 0x1215c, 0x1222c, 0x12304, 0x123d4,
+0x12430, 0x1250c, 0x12534, 0x12610, 0x12638, 0x127e0,
+0x12808, 0x129b0, 0x12ba8, 0x12e3c, 0x12d50, 0x12e3c,
+0x12e68, 0x129d8, 0x12b80, 0x0, 0x13254, 0x132b4,
+0x13330, 0x1335c, 0x133ac, 0x133e8, 0x1341c, 0x134a8,
+0x13560, 0x13630, 0x13670, 0x136f4, 0x13750, 0x13884,
+0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0,
+0x73746d61, 0x634c4e4b, 0x0, 0x0, 0x0 };
/* Generated by genfw.c */
int tigon2FwReleaseMajor = 0xc;
int tigon2FwReleaseMinor = 0x1;
-int tigon2FwReleaseFix = 0x4;
+int tigon2FwReleaseFix = 0x6;
u32 tigon2FwStartAddr = 0x4000;
u32 tigon2FwTextAddr = 0x4000;
-int tigon2FwTextLen = 0xe480;
-u32 tigon2FwDataAddr = 0x131d0;
+int tigon2FwTextLen = 0xe5b0;
+u32 tigon2FwDataAddr = 0x13330;
int tigon2FwDataLen = 0x170;
-u32 tigon2FwRodataAddr = 0x12480;
-int tigon2FwRodataLen = 0xd30;
-u32 tigon2FwBssAddr = 0x133f0;
+u32 tigon2FwRodataAddr = 0x125b0;
+int tigon2FwRodataLen = 0xd60;
+u32 tigon2FwBssAddr = 0x13550;
int tigon2FwBssLen = 0x20c0;
-u32 tigon2FwSbssAddr = 0x13340;
+u32 tigon2FwSbssAddr = 0x134a0;
int tigon2FwSbssLen = 0xa8;
-u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
+u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001,
-0x8fbd3220, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0,
-0xd, 0x3c1d0001, 0x8fbd3224, 0x3a0f021, 0x3c100000, 0x26104000,
+0x8fbd3380, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0,
+0xd, 0x3c1d0001, 0x8fbd3384, 0x3a0f021, 0x3c100000, 0x26104000,
0xc0016fe, 0x0, 0xd, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -2930,14 +2952,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x2000008, 0x0,
0x8001671, 0x3c0a0001, 0x8001671, 0x3c0a0002, 0x8001671, 0x0,
-0x8002994, 0x0, 0x8001671, 0x3c0a0003, 0x8001671, 0x3c0a0004,
-0x8003110, 0x0, 0x80019ba, 0x0, 0x8003608, 0x0,
-0x8003597, 0x0, 0x8001671, 0x3c0a0006, 0x8001671, 0x3c0a0007,
-0x8001671, 0x3c0a0008, 0x8001671, 0x3c0a0009, 0x8003679, 0x0,
-0x8002bd5, 0x0, 0x8001671, 0x3c0a000b, 0x8001671, 0x3c0a000c,
-0x8001671, 0x3c0a000d, 0x80026e0, 0x0, 0x80026b3, 0x0,
+0x80029b8, 0x0, 0x8001671, 0x3c0a0003, 0x8001671, 0x3c0a0004,
+0x8003134, 0x0, 0x80019ba, 0x0, 0x8003653, 0x0,
+0x80035e2, 0x0, 0x8001671, 0x3c0a0006, 0x8001671, 0x3c0a0007,
+0x8001671, 0x3c0a0008, 0x8001671, 0x3c0a0009, 0x80036c4, 0x0,
+0x8002bf9, 0x0, 0x8001671, 0x3c0a000b, 0x8001671, 0x3c0a000c,
+0x8001671, 0x3c0a000d, 0x80026ee, 0x0, 0x80026ad, 0x0,
0x8001671, 0x3c0a000e, 0x8001f40, 0x0, 0x80018c9, 0x0,
-0x800196b, 0x0, 0x80038f7, 0x0, 0x80038e1, 0x0,
+0x800196b, 0x0, 0x8003943, 0x0, 0x800392d, 0x0,
0x8001671, 0x0, 0x800184d, 0x0, 0x8001893, 0x0,
0x8001671, 0x3c0a0013, 0x8001671, 0x3c0a0014, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
@@ -2950,68 +2972,68 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xc0028d0, 0xd021, 0x8f820040,
+0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xc0028f4, 0xd021, 0x8f820040,
0x3c03f000, 0x431824, 0x3c025000, 0x10620005, 0x3c026000, 0x1062001a,
0x24020003, 0x10000030, 0x0, 0x8f820050, 0x3c030010, 0x431024,
-0x50400013, 0x24020003, 0x3c030001, 0x2463c2d0, 0x3c020001, 0x2442c354,
-0x431023, 0x3c010001, 0xac2333b8, 0x8f830140, 0x3c040001, 0x2484c35c,
-0x3c010001, 0xac2233a4, 0x3c020001, 0x2442c3c4, 0x3c010001, 0xac2031d8,
-0x10000013, 0x441023, 0x3c030001, 0x2463c3cc, 0xaf8200ec, 0x3c020001,
-0x2442c408, 0x431023, 0x3c010001, 0xac2333b8, 0x8f830140, 0x3c040001,
-0x2484c410, 0x3c010001, 0xac2233a4, 0x3c020001, 0x2442c438, 0x441023,
-0x3c0100c0, 0xac203ffc, 0x3c010001, 0xac2433b0, 0x3c010001, 0xac2233ac,
+0x50400013, 0x24020003, 0x3c030001, 0x2463c360, 0x3c020001, 0x2442c3e4,
+0x431023, 0x3c010001, 0xac233518, 0x8f830140, 0x3c040001, 0x2484c3ec,
+0x3c010001, 0xac223504, 0x3c020001, 0x2442c454, 0x3c010001, 0xac203338,
+0x10000013, 0x441023, 0x3c030001, 0x2463c45c, 0xaf8200ec, 0x3c020001,
+0x2442c498, 0x431023, 0x3c010001, 0xac233518, 0x8f830140, 0x3c040001,
+0x2484c4a0, 0x3c010001, 0xac223504, 0x3c020001, 0x2442c4c8, 0x441023,
+0x3c0100c0, 0xac203ffc, 0x3c010001, 0xac243510, 0x3c010001, 0xac22350c,
0x34630004, 0xaf830140, 0xc00169c, 0x0, 0x402821, 0x3c010001,
-0xac253350, 0x3c020008, 0x10a2002c, 0x45102b, 0x14400006, 0x3c020010,
+0xac2534b0, 0x3c020008, 0x10a2002c, 0x45102b, 0x14400006, 0x3c020010,
0x3c020004, 0x10a20007, 0x3c02ffff, 0x1000005b, 0x0, 0x10a20045,
-0x3c030003, 0x10000057, 0x0, 0x34422e10, 0x3c030001, 0x246354b0,
-0x3c040001, 0x8c8431d4, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8,
-0x2403f000, 0xa32824, 0x51082, 0x431024, 0x3c010001, 0xac223340,
-0xa21023, 0x3c010001, 0xac223348, 0x3402a000, 0x3c010001, 0xac223358,
-0x24020008, 0x3c010001, 0xac223360, 0x2402001f, 0x3c010001, 0xac223368,
-0x24020016, 0x3c010001, 0xac22334c, 0x10000041, 0x3c08ffff, 0x3c02ffff,
-0x34422e10, 0x3c030001, 0x246354b0, 0x3c040001, 0x8c8431d4, 0xa31823,
+0x3c030003, 0x10000057, 0x0, 0x34422e10, 0x3c030001, 0x24635610,
+0x3c040001, 0x8c843334, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8,
+0x2403f000, 0xa32824, 0x51082, 0x431024, 0x3c010001, 0xac2234a0,
+0xa21023, 0x3c010001, 0xac2234a8, 0x3402a000, 0x3c010001, 0xac2234b8,
+0x24020008, 0x3c010001, 0xac2234c0, 0x2402001f, 0x3c010001, 0xac2234c8,
+0x24020016, 0x3c010001, 0xac2234ac, 0x10000041, 0x3c08ffff, 0x3c02ffff,
+0x34422e10, 0x3c030001, 0x24635610, 0x3c040001, 0x8c843334, 0xa31823,
0x14800002, 0x622821, 0x24a5faa8, 0x2403f000, 0xa32824, 0x3c040003,
-0x34842000, 0x510c2, 0x431024, 0x3c010001, 0xac223340, 0xa21023,
-0x3c010001, 0xac223348, 0x24020008, 0x3c010001, 0xac223360, 0x2402001f,
-0x3c010001, 0xac223368, 0x24020016, 0x3c010001, 0xac243358, 0x3c010001,
-0xac22334c, 0x1000001f, 0x3c08ffff, 0x34632000, 0x3c020001, 0x3c010001,
-0xac223340, 0x3c020007, 0x3c010001, 0xac223348, 0x24020008, 0x3c010001,
-0xac223360, 0x2402001f, 0x3c010001, 0xac223368, 0x24020016, 0x3c010001,
-0xac233358, 0x3c010001, 0xac22334c, 0x1000000b, 0x3c08ffff, 0x3c040001,
-0x24842540, 0x3c050001, 0x8ca53350, 0x3021, 0x3821, 0xafa00010,
-0xc0028eb, 0xafa00014, 0x3c08ffff, 0x35087e10, 0x3c0500bf, 0x34a5f000,
-0x3c0600bf, 0x34c6e000, 0x3c070001, 0x8ce73340, 0x3c040001, 0x8c843348,
-0x3c030020, 0x3c090001, 0x8d2931d0, 0x671023, 0x441023, 0x245bb000,
-0x641823, 0x3c010001, 0xac233354, 0x671823, 0x27620ffc, 0x3c010001,
-0xac223220, 0x27621ffc, 0xbb2823, 0xdb3023, 0x3c010001, 0xac233344,
-0x3c010001, 0xac223224, 0xaf850150, 0xaf860250, 0x1120001b, 0x368b821,
-0x33620fff, 0x10400008, 0x24050019, 0x3c040001, 0x2484254c, 0x3603021,
-0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x3c1d0001, 0x8fbd31dc,
-0x3a0f021, 0xc001684, 0x0, 0x3c020001, 0x8c4231e0, 0x3c030001,
-0x8c6331e4, 0x2442fe00, 0x24630200, 0x3c010001, 0xac2231e0, 0x3c010001,
-0x10000004, 0xac2331e4, 0x3c1d0001, 0x8fbd3220, 0x3a0f021, 0x3c020001,
-0x8c4231d4, 0x1040000d, 0x26f6faa8, 0x3c020001, 0x8c4231e0, 0x3c030001,
-0x8c6331e4, 0x3c160001, 0x8ed631e4, 0x2442faa8, 0x24630558, 0x3c010001,
-0xac2231e0, 0x3c010001, 0xac2331e4, 0x3c020001, 0x8c4231d8, 0x14400003,
-0x0, 0x3c010001, 0xac2031e0, 0xc0011ca, 0x0, 0x8fbf0018,
+0x34842000, 0x510c2, 0x431024, 0x3c010001, 0xac2234a0, 0xa21023,
+0x3c010001, 0xac2234a8, 0x24020008, 0x3c010001, 0xac2234c0, 0x2402001f,
+0x3c010001, 0xac2234c8, 0x24020016, 0x3c010001, 0xac2434b8, 0x3c010001,
+0xac2234ac, 0x1000001f, 0x3c08ffff, 0x34632000, 0x3c020001, 0x3c010001,
+0xac2234a0, 0x3c020007, 0x3c010001, 0xac2234a8, 0x24020008, 0x3c010001,
+0xac2234c0, 0x2402001f, 0x3c010001, 0xac2234c8, 0x24020016, 0x3c010001,
+0xac2334b8, 0x3c010001, 0xac2234ac, 0x1000000b, 0x3c08ffff, 0x3c040001,
+0x24842670, 0x3c050001, 0x8ca534b0, 0x3021, 0x3821, 0xafa00010,
+0xc00290f, 0xafa00014, 0x3c08ffff, 0x35087e10, 0x3c0500bf, 0x34a5f000,
+0x3c0600bf, 0x34c6e000, 0x3c070001, 0x8ce734a0, 0x3c040001, 0x8c8434a8,
+0x3c030020, 0x3c090001, 0x8d293330, 0x671023, 0x441023, 0x245bb000,
+0x641823, 0x3c010001, 0xac2334b4, 0x671823, 0x27620ffc, 0x3c010001,
+0xac223380, 0x27621ffc, 0xbb2823, 0xdb3023, 0x3c010001, 0xac2334a4,
+0x3c010001, 0xac223384, 0xaf850150, 0xaf860250, 0x1120001b, 0x368b821,
+0x33620fff, 0x10400008, 0x24050019, 0x3c040001, 0x2484267c, 0x3603021,
+0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x3c1d0001, 0x8fbd333c,
+0x3a0f021, 0xc001684, 0x0, 0x3c020001, 0x8c423340, 0x3c030001,
+0x8c633344, 0x2442fe00, 0x24630200, 0x3c010001, 0xac223340, 0x3c010001,
+0x10000004, 0xac233344, 0x3c1d0001, 0x8fbd3380, 0x3a0f021, 0x3c020001,
+0x8c423334, 0x1040000d, 0x26f6faa8, 0x3c020001, 0x8c423340, 0x3c030001,
+0x8c633344, 0x3c160001, 0x8ed63344, 0x2442faa8, 0x24630558, 0x3c010001,
+0xac223340, 0x3c010001, 0xac233344, 0x3c020001, 0x8c423338, 0x14400003,
+0x0, 0x3c010001, 0xac203340, 0xc0011ca, 0x0, 0x8fbf0018,
0x3e00008, 0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb50058,
0xafb30054, 0xafb10050, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240,
-0x3c020001, 0x8c4231e0, 0x3c030001, 0x8c6331e4, 0xaf800048, 0x8f840048,
+0x3c020001, 0x8c423340, 0x3c030001, 0x8c633344, 0xaf800048, 0x8f840048,
0x3c120000, 0x26524100, 0xa3a00047, 0xafa20034, 0x14800005, 0xafa30030,
0xaf800048, 0x8f820048, 0x10400004, 0x0, 0xaf800048, 0x10000003,
-0x2e02021, 0xaf80004c, 0x2e02021, 0xc00296c, 0x340581f0, 0x2c02021,
-0xc00296c, 0x24050558, 0x3c020001, 0x8c423344, 0x3c030001, 0x8c633340,
-0x3c040001, 0x8c843348, 0x3c050001, 0x8ca53358, 0x3c060001, 0x8cc63360,
-0x3c070001, 0x8ce73368, 0x3c080001, 0x8d08334c, 0xaec20534, 0x3c020001,
-0x8c423354, 0x8ec90534, 0xaec50544, 0x3c050001, 0x8ca53350, 0xaec00000,
+0x2e02021, 0xaf80004c, 0x2e02021, 0xc002990, 0x340581f0, 0x2c02021,
+0xc002990, 0x24050558, 0x3c020001, 0x8c4234a4, 0x3c030001, 0x8c6334a0,
+0x3c040001, 0x8c8434a8, 0x3c050001, 0x8ca534b8, 0x3c060001, 0x8cc634c0,
+0x3c070001, 0x8ce734c8, 0x3c080001, 0x8d0834ac, 0xaec20534, 0x3c020001,
+0x8c4234b4, 0x8ec90534, 0xaec50544, 0x3c050001, 0x8ca534b0, 0xaec00000,
0xaec3053c, 0xaec40540, 0xaec60548, 0xaec7054c, 0xaec80550, 0xaec20538,
0xafa90010, 0x8ec20538, 0xafa20014, 0x8ec6053c, 0x8ec70540, 0x3c040001,
-0xc0028eb, 0x24842558, 0xafb70010, 0xafb60014, 0x8ec60544, 0x8ec70548,
-0x3c040001, 0x24842560, 0xc0028eb, 0x24050001, 0x3c040001, 0x24842568,
-0x24050001, 0x24060001, 0x24070001, 0xafa00010, 0xc0028eb, 0xafa00014,
-0x3c020001, 0x8c423350, 0x3603821, 0x3c060001, 0x24c654b0, 0x2448ffff,
+0xc00290f, 0x24842688, 0xafb70010, 0xafb60014, 0x8ec60544, 0x8ec70548,
+0x3c040001, 0x24842690, 0xc00290f, 0x24050001, 0x3c040001, 0x24842698,
+0x24050001, 0x24060001, 0x24070001, 0xafa00010, 0xc00290f, 0xafa00014,
+0x3c020001, 0x8c4234b0, 0x3603821, 0x3c060001, 0x24c65610, 0x2448ffff,
0x1061824, 0xe81024, 0x43102b, 0x10400006, 0x24050002, 0x3c040001,
-0x24842570, 0xafa80010, 0xc0028eb, 0xafa00014, 0x24020001, 0xa2c20529,
+0x248426a0, 0xafa80010, 0xc00290f, 0xafa00014, 0x24020001, 0xa2c20529,
0xaf800054, 0xaf80011c, 0x8f420218, 0x30420002, 0x10400009, 0x0,
0x8f420220, 0x3c030002, 0x34630004, 0x431025, 0xaec20008, 0x8f42021c,
0x10000008, 0x34420004, 0x8f420220, 0x3c030002, 0x34630006, 0x431025,
@@ -3028,109 +3050,109 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x9482000a, 0xaca2009c, 0x8ca200b0, 0x8ec30010, 0x431025, 0xaca200b0,
0x8f8200b0, 0x30420004, 0x1440fffd, 0x0, 0x8ee20448, 0x8ee3044c,
0xaee304bc, 0x8ee204bc, 0x2442e000, 0x2c422001, 0x1440000d, 0x26c40128,
-0x8ee20448, 0x8ee3044c, 0x3c040001, 0x2484257c, 0x3c050001, 0xafa00010,
-0xafa00014, 0x8ee704bc, 0x34a5f000, 0xc0028eb, 0x603021, 0x26c40128,
-0xc00296c, 0x24050400, 0x27440080, 0xc00296c, 0x24050080, 0x8f42025c,
-0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xc00297e,
+0x8ee20448, 0x8ee3044c, 0x3c040001, 0x248426ac, 0x3c050001, 0xafa00010,
+0xafa00014, 0x8ee704bc, 0x34a5f000, 0xc00290f, 0x603021, 0x26c40128,
+0xc002990, 0x24050400, 0x27440080, 0xc002990, 0x24050080, 0x8f42025c,
+0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xc0029a2,
0xaec20160, 0x3c043b9a, 0x3484ca00, 0x2821, 0x24020006, 0x24030002,
0xaec2015c, 0x240203e8, 0xaec3016c, 0xaec30168, 0xaec40164, 0xaec201fc,
-0x24020001, 0xaec301f8, 0xaec20204, 0x3c030001, 0x651821, 0x906331e8,
+0x24020001, 0xaec301f8, 0xaec20204, 0x3c030001, 0x651821, 0x90633348,
0x2c51021, 0x24a50001, 0xa0430194, 0x2ca2000f, 0x1440fff8, 0x2c51821,
0x8f820040, 0x24a50001, 0x21702, 0x24420030, 0xa0620194, 0x2c51021,
-0xa0400194, 0xafa00010, 0x8fa20034, 0x3c040001, 0x24842588, 0xafa20014,
-0x8fa60030, 0x3821, 0xc0028eb, 0x2821, 0x3c040000, 0x24845990,
+0xa0400194, 0xafa00010, 0x8fa20034, 0x3c040001, 0x248426b8, 0xafa20014,
+0x8fa60030, 0x3821, 0xc00290f, 0x2821, 0x3c040000, 0x24845990,
0x24050010, 0x27b30030, 0x2603021, 0x27b10034, 0xc0016be, 0x2203821,
-0x3c030001, 0x8c6331d8, 0x3c15f000, 0x1060000a, 0xafa2003c, 0x8fa30030,
+0x3c030001, 0x8c633338, 0x3c15f000, 0x1060000a, 0xafa2003c, 0x8fa30030,
0x2405ff00, 0x8fa20034, 0x246400ff, 0x852024, 0x831823, 0x431023,
0xafa20034, 0xafa40030, 0x3c040000, 0x24844100, 0x24050108, 0x2603021,
0xc0016be, 0x2203821, 0x96e30452, 0x30630003, 0x1060005f, 0x409021,
0x8f820050, 0x3c030010, 0x431024, 0x10400021, 0x0, 0x8f820040,
0x3c035000, 0x551024, 0x14430009, 0x0, 0x96e60452, 0x8f820050,
-0xafa00014, 0xafa20010, 0x8f870040, 0x3c040001, 0x1000000d, 0x24842594,
+0xafa00014, 0xafa20010, 0x8f870040, 0x3c040001, 0x1000000d, 0x248426c4,
0x8f420218, 0x30420040, 0x1040000d, 0x24020001, 0x8f820050, 0x96e60452,
-0xafa20010, 0x8f420218, 0xafa20014, 0x8f870040, 0x3c040001, 0x2484259c,
-0xc0028eb, 0x2821, 0x10000004, 0x0, 0x3c010001, 0x370821,
-0xa02281ec, 0x3c040001, 0x24849a48, 0x3c050001, 0x24a59ac4, 0xa42823,
+0xafa20010, 0x8f420218, 0xafa20014, 0x8f870040, 0x3c040001, 0x248426cc,
+0xc00290f, 0x2821, 0x10000004, 0x0, 0x3c010001, 0x370821,
+0xa02281ec, 0x3c040001, 0x24849a34, 0x3c050001, 0x24a59aac, 0xa42823,
0x27b30030, 0x2603021, 0x8ec3000c, 0x27b10034, 0x2203821, 0x24020001,
0xa2c20020, 0xa2c20021, 0x34630a00, 0xc0016be, 0xaec3000c, 0x3c040001,
-0x2484ab64, 0x3c050001, 0x24a5af4c, 0xa42823, 0x2603021, 0x2203821,
-0xc0016be, 0xaec200a4, 0x3c040001, 0x2484b418, 0x3c050001, 0x24a5c2c8,
-0xa42823, 0x2603021, 0x3c010001, 0xac22339c, 0xc0016be, 0x2203821,
-0x3c040001, 0x2484dacc, 0x3c050001, 0x24a5e290, 0xa42823, 0x2603021,
-0x3c010001, 0xac2233a0, 0xc0016be, 0x2203821, 0x3c040001, 0x248425a4,
-0x96e60452, 0x24050011, 0x3821, 0x3c010001, 0xac2233bc, 0xafa00010,
-0xc0028eb, 0xafa00014, 0x10000028, 0x0, 0x3c040001, 0x2484989c,
-0x3c050001, 0x24a59a40, 0xa42823, 0x2603021, 0xc0016be, 0x2203821,
-0x3c040001, 0x2484a650, 0x3c050001, 0x24a5ab5c, 0xa42823, 0x2603021,
-0x2203821, 0xc0016be, 0xaec200a4, 0x3c040001, 0x2484af54, 0x3c050001,
-0x24a5b410, 0xa42823, 0x2603021, 0x3c010001, 0xac22339c, 0xc0016be,
-0x2203821, 0x3c040001, 0x2484d9e4, 0x3c050001, 0x24a5dac4, 0xa42823,
-0x2603021, 0x3c010001, 0xac2233a0, 0xc0016be, 0x2203821, 0x3c010001,
-0xac2233bc, 0x3c020001, 0x8c42339c, 0x3c050fff, 0x34a5ffff, 0x3c030001,
-0x8c6333a0, 0x3c040800, 0x451024, 0x21082, 0x441025, 0x651824,
-0xae420020, 0x3c020001, 0x8c4233bc, 0x31882, 0x641825, 0xae430080,
+0x2484abf4, 0x3c050001, 0x24a5afdc, 0xa42823, 0x2603021, 0x2203821,
+0xc0016be, 0xaec200a4, 0x3c040001, 0x2484b4a8, 0x3c050001, 0x24a5c358,
+0xa42823, 0x2603021, 0x3c010001, 0xac2234fc, 0xc0016be, 0x2203821,
+0x3c040001, 0x2484dbf8, 0x3c050001, 0x24a5e3bc, 0xa42823, 0x2603021,
+0x3c010001, 0xac223500, 0xc0016be, 0x2203821, 0x3c040001, 0x248426d4,
+0x96e60452, 0x24050011, 0x3821, 0x3c010001, 0xac22351c, 0xafa00010,
+0xc00290f, 0xafa00014, 0x10000028, 0x0, 0x3c040001, 0x24849890,
+0x3c050001, 0x24a59a2c, 0xa42823, 0x2603021, 0xc0016be, 0x2203821,
+0x3c040001, 0x2484a6e0, 0x3c050001, 0x24a5abec, 0xa42823, 0x2603021,
+0x2203821, 0xc0016be, 0xaec200a4, 0x3c040001, 0x2484afe4, 0x3c050001,
+0x24a5b4a0, 0xa42823, 0x2603021, 0x3c010001, 0xac2234fc, 0xc0016be,
+0x2203821, 0x3c040001, 0x2484db10, 0x3c050001, 0x24a5dbf0, 0xa42823,
+0x2603021, 0x3c010001, 0xac223500, 0xc0016be, 0x2203821, 0x3c010001,
+0xac22351c, 0x3c020001, 0x8c4234fc, 0x3c050fff, 0x34a5ffff, 0x3c030001,
+0x8c633500, 0x3c040800, 0x451024, 0x21082, 0x441025, 0x651824,
+0xae420020, 0x3c020001, 0x8c42351c, 0x31882, 0x641825, 0xae430080,
0x451024, 0x21082, 0x441025, 0xae420078, 0x96e20462, 0x30420003,
0x14400009, 0x0, 0x96e20472, 0x30420003, 0x1040007f, 0x27b30030,
0x96e20462, 0x30420003, 0x1040006d, 0x3c020700, 0x96e20472, 0x30420003,
0x10400069, 0x3c020700, 0x96e30472, 0x96e20462, 0x14620065, 0x3c020700,
0x8f82005c, 0x3c030080, 0x431024, 0x1040000b, 0x0, 0x8f820050,
0x96e60462, 0xafa20010, 0x8f82005c, 0xafa20014, 0x8f870040, 0x3c040001,
-0x248425b0, 0xc0028eb, 0x24051977, 0x8f820050, 0x3c030010, 0x431024,
+0x248426e0, 0xc00290f, 0x24051977, 0x8f820050, 0x3c030010, 0x431024,
0x10400022, 0x0, 0x8f820040, 0x3c03f000, 0x431024, 0x3c035000,
0x14430009, 0x0, 0x96e60462, 0x8f820050, 0xafa00014, 0xafa20010,
-0x8f870040, 0x3c040001, 0x1000000d, 0x24842594, 0x8f420218, 0x30420040,
+0x8f870040, 0x3c040001, 0x1000000d, 0x248426c4, 0x8f420218, 0x30420040,
0x1040000d, 0x24020001, 0x8f820050, 0x96e60462, 0xafa20010, 0x8f420218,
-0xafa20014, 0x8f870040, 0x3c040001, 0x2484259c, 0xc0028eb, 0x24050001,
+0xafa20014, 0x8f870040, 0x3c040001, 0x248426cc, 0xc00290f, 0x24050001,
0x10000004, 0x0, 0x3c010001, 0x370821, 0xa02281ec, 0x3c040001,
-0x2484981c, 0x3c050001, 0x24a59894, 0xa42823, 0x27b30030, 0x2603021,
+0x24849810, 0x3c050001, 0x24a59888, 0xa42823, 0x27b30030, 0x2603021,
0x8ec30004, 0x27b10034, 0x2203821, 0x24020001, 0xa2c2004c, 0x34630e00,
-0xc0016be, 0xaec30004, 0x3c040001, 0x2484cf2c, 0x3c050001, 0x24a5d654,
+0xc0016be, 0xaec30004, 0x3c040001, 0x2484d058, 0x3c050001, 0x24a5d780,
0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, 0x3c040001,
-0x2484dacc, 0x3c050001, 0x24a5e290, 0xa42823, 0x2603021, 0x3c010001,
-0xac2233b4, 0xc0016be, 0x2203821, 0x3c040001, 0x248425bc, 0x21900,
+0x2484dbf8, 0x3c050001, 0x24a5e3bc, 0xa42823, 0x2603021, 0x3c010001,
+0xac223514, 0xc0016be, 0x2203821, 0x3c040001, 0x248426ec, 0x21900,
0x31982, 0x3c050800, 0x651825, 0xae430078, 0x96e60462, 0x24050012,
-0x3c010001, 0xac2233bc, 0x1000000a, 0x3821, 0x34423000, 0x240a0001,
-0x3c040001, 0x248425c8, 0x3405f001, 0x3021, 0x3821, 0xa3aa0047,
-0xafa20020, 0xafa00010, 0xc0028eb, 0xafa00014, 0x10000015, 0x0,
-0x3c040001, 0x2484960c, 0x3c050001, 0x24a59814, 0xa42823, 0x2603021,
-0x27b10034, 0xc0016be, 0x2203821, 0x3c040001, 0x2484c4ec, 0x3c050001,
-0x24a5cf24, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8,
-0x3c010001, 0xac2233b4, 0x3c020001, 0x8c4233b4, 0x3c030800, 0x21100,
+0x3c010001, 0xac22351c, 0x1000000a, 0x3821, 0x34423000, 0x240a0001,
+0x3c040001, 0x248426f8, 0x3405f001, 0x3021, 0x3821, 0xa3aa0047,
+0xafa20020, 0xafa00010, 0xc00290f, 0xafa00014, 0x10000015, 0x0,
+0x3c040001, 0x2484960c, 0x3c050001, 0x24a59808, 0xa42823, 0x2603021,
+0x27b10034, 0xc0016be, 0x2203821, 0x3c040001, 0x2484c57c, 0x3c050001,
+0x24a5d050, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8,
+0x3c010001, 0xac223514, 0x3c020001, 0x8c423514, 0x3c030800, 0x21100,
0x21182, 0x431025, 0xae420038, 0x8f420218, 0x30420040, 0x14400004,
0x24020001, 0x3c010001, 0x370821, 0xa02281ec, 0x96e20462, 0x30420010,
0x14400009, 0x0, 0x96e20472, 0x30420010, 0x10400021, 0x0,
0x96e20462, 0x30420010, 0x10400005, 0x3c020700, 0x96e20472, 0x30420010,
0x14400011, 0x3c020700, 0x34423000, 0x240a0001, 0xa3aa0047, 0xafa20020,
0x8ee20154, 0x96e60462, 0x96e70472, 0x24420001, 0xaee20154, 0x8ee20154,
-0x3c040001, 0x248425d4, 0x3405f002, 0xafa00010, 0xc0028eb, 0xafa00014,
-0x96e60472, 0x96e70462, 0x3c040001, 0x248425dc, 0x24050012, 0xafa00010,
-0xc0028eb, 0xafa00014, 0x3c040001, 0x2484d65c, 0x3c050001, 0x24a5d818,
+0x3c040001, 0x24842704, 0x3405f002, 0xafa00010, 0xc00290f, 0xafa00014,
+0x96e60472, 0x96e70462, 0x3c040001, 0x2484270c, 0x24050012, 0xafa00010,
+0xc00290f, 0xafa00014, 0x3c040001, 0x2484d788, 0x3c050001, 0x24a5d944,
0xa42823, 0x27b30030, 0x2603021, 0x27b10034, 0xc0016be, 0x2203821,
-0x3c1e0fff, 0x37deffff, 0x3c040001, 0x2484d820, 0x3c050001, 0x24a5d9dc,
-0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2233a8, 0x5e1024,
+0x3c1e0fff, 0x37deffff, 0x3c040001, 0x2484d94c, 0x3c050001, 0x24a5db08,
+0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac223508, 0x5e1024,
0x21082, 0x3c150800, 0x551025, 0xc0016be, 0xae420050, 0x3c040000,
0x24847d00, 0x3c050000, 0x24a57f50, 0xa42823, 0x2603021, 0x2203821,
-0x3c010001, 0xac2233c0, 0x5e1024, 0x21082, 0x551025, 0xc0016be,
+0x3c010001, 0xac223520, 0x5e1024, 0x21082, 0x551025, 0xc0016be,
0xae420048, 0x3c040000, 0x24846134, 0x3c050000, 0x24a56244, 0xa42823,
-0x2603021, 0x2203821, 0x3c010001, 0xac223388, 0x5e1024, 0x21082,
+0x2603021, 0x2203821, 0x3c010001, 0xac2234e8, 0x5e1024, 0x21082,
0x551025, 0xc0016be, 0xae4200b8, 0x3c040000, 0x2484624c, 0x3c050000,
-0x24a5631c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac22337c,
+0x24a5631c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2234dc,
0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200e8, 0x3c040000,
0x24846324, 0x3c050000, 0x24a565a4, 0xa42823, 0x2603021, 0x2203821,
-0x3c010001, 0xac22336c, 0x5e1024, 0x21082, 0x551025, 0xc0016be,
+0x3c010001, 0xac2234cc, 0x5e1024, 0x21082, 0x551025, 0xc0016be,
0xae4200f0, 0x3c040000, 0x248465ac, 0x3c050000, 0x24a566e0, 0xa42823,
-0x2603021, 0x2203821, 0x3c010001, 0xac223374, 0x5e1024, 0x21082,
-0x551025, 0xc0016be, 0xae4200c0, 0x3c040001, 0x2484e3dc, 0x3c050001,
-0x24a5e98c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac223380,
+0x2603021, 0x2203821, 0x3c010001, 0xac2234d4, 0x5e1024, 0x21082,
+0x551025, 0xc0016be, 0xae4200c0, 0x3c040001, 0x2484e50c, 0x3c050001,
+0x24a5eabc, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2234e0,
0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200c8, 0x3c040001,
-0x2484ed00, 0x3c050001, 0x24a5edd8, 0xa42823, 0x2603021, 0x2203821,
-0x3c010001, 0xac2233c4, 0x5e1024, 0x21082, 0x551025, 0xc0016be,
-0xae4200d0, 0x3c040001, 0x8c8433b8, 0x3c050001, 0x8ca533a4, 0x2603021,
-0x2203821, 0xc0016be, 0xaec200ac, 0x3c040001, 0x8c8433b0, 0x3c050001,
-0x8ca533ac, 0x2603021, 0x3c010001, 0xac2233b8, 0xc0016be, 0x2203821,
-0x3c010001, 0xac2233b0, 0x3c070001, 0xf73821, 0x90e781ec, 0xafa00010,
-0x8fa20034, 0xafa20014, 0x8fa60030, 0x3c040001, 0x248425e8, 0xc0028eb,
-0x2821, 0x8faa003c, 0xc003beb, 0x1408021, 0xc0038a8, 0x0,
+0x2484ee30, 0x3c050001, 0x24a5ef08, 0xa42823, 0x2603021, 0x2203821,
+0x3c010001, 0xac223524, 0x5e1024, 0x21082, 0x551025, 0xc0016be,
+0xae4200d0, 0x3c040001, 0x8c843518, 0x3c050001, 0x8ca53504, 0x2603021,
+0x2203821, 0xc0016be, 0xaec200ac, 0x3c040001, 0x8c843510, 0x3c050001,
+0x8ca5350c, 0x2603021, 0x3c010001, 0xac223518, 0xc0016be, 0x2203821,
+0x3c010001, 0xac223510, 0x3c070001, 0xf73821, 0x90e781ec, 0xafa00010,
+0x8fa20034, 0xafa20014, 0x8fa60030, 0x3c040001, 0x24842718, 0xc00290f,
+0x2821, 0x8faa003c, 0xc003c37, 0x1408021, 0xc0038f4, 0x0,
0xc002548, 0x0, 0xaec0002c, 0xaf400228, 0xaf40022c, 0xaee004a8,
0xaec00014, 0xaec00018, 0xaec00024, 0x96e20450, 0x2442ffff, 0xaec20028,
0x3c010001, 0x370821, 0xac2081d4, 0xaec00038, 0xaec00044, 0xaec0003c,
@@ -3141,55 +3163,55 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xa2c00115, 0x3c1433d8, 0x3694c348, 0x3c020800, 0x34420080, 0x3c040000,
0x248459dc, 0x3c050000, 0x24a55a08, 0xa42823, 0x2603021, 0x2203821,
0xaf820060, 0x2402ffff, 0xaec00030, 0xaec00034, 0xc0016be, 0xaf820064,
-0x3c010001, 0xac223364, 0x5e1024, 0x21082, 0x551025, 0xc00181c,
+0x3c010001, 0xac2234c4, 0x5e1024, 0x21082, 0x551025, 0xc00181c,
0xae420000, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 0x3c020000,
0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 0x551024, 0x14400005,
-0x3c030800, 0x8f820060, 0x431024, 0x1040fffd, 0x0, 0xc0038b5,
+0x3c030800, 0x8f820060, 0x431024, 0x1040fffd, 0x0, 0xc003901,
0x0, 0x3c020100, 0xafa20028, 0x8ec3002c, 0x240200ff, 0x10620003,
0x8821, 0x8ec2002c, 0x24510001, 0x8f420228, 0x1622000f, 0x24070008,
-0x3c040001, 0x248424fc, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
-0x3c050009, 0xc0028eb, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0,
+0x3c040001, 0x2484262c, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
+0x3c050009, 0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0,
0x10000046, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8fa30028,
0x8fa4002c, 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c,
0x8ec6002c, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0,
0x604821, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x832021,
0x630c0, 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021,
-0x5440000c, 0xaed1002c, 0x3c040001, 0x24842508, 0xafa00010, 0xafa00014,
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d,
+0x5440000c, 0xaed1002c, 0x3c040001, 0x24842638, 0xafa00010, 0xafa00014,
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d,
0x0, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120,
0x24020011, 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008,
-0x40f809, 0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842510,
-0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb,
+0x40f809, 0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842640,
+0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f,
0x34a5f001, 0x8ec202a4, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x8ec20248,
0x24420001, 0xaec20248, 0x8ec20248, 0x93a20047, 0x10400070, 0x240200ff,
0x8ec3002c, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001,
-0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 0x248424fc,
-0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb,
+0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 0x2484262c,
+0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f,
0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 0x8ec202a0,
0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0,
0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008,
0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 0x604821,
0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 0xafa20018,
0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, 0xaed1002c,
-0x3c040001, 0x24842508, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
-0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488,
+0x3c040001, 0x24842638, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
+0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488,
0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 0xafa20010,
0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c,
-0x1440000e, 0x0, 0x3c040001, 0x24842510, 0xafa00010, 0xafa00014,
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, 0x8ec202a4,
-0x24420001, 0xaec202a4, 0x8ec202a4, 0x3c040001, 0x248425f4, 0x8ec20254,
+0x1440000e, 0x0, 0x3c040001, 0x24842640, 0xafa00010, 0xafa00014,
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 0x8ec202a4,
+0x24420001, 0xaec202a4, 0x8ec202a4, 0x3c040001, 0x24842724, 0x8ec20254,
0x3c050009, 0x34a59999, 0x24420001, 0xaec20254, 0x8ec20254, 0x3021,
-0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x10000004, 0x0,
+0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x10000004, 0x0,
0x8f420264, 0x10400005, 0x0, 0x8f8200a0, 0x30420004, 0x1440fffa,
0x0, 0x8f820044, 0x34420004, 0xaf820044, 0x8ec2026c, 0x24420001,
0xaec2026c, 0x8ec2026c, 0x8f8200d8, 0x8f8300d4, 0x431023, 0x2442fff8,
0xaec20088, 0x8ec20088, 0x4410006, 0x24020001, 0x8ec20088, 0x8ec3053c,
0x431021, 0xaec20088, 0x24020001, 0xaec20070, 0x96e20452, 0x30420010,
0x10400005, 0x0, 0x8f820214, 0x3c038100, 0x431025, 0xaf820214,
-0x3c020001, 0x8c4232a8, 0x30420001, 0x10400007, 0x0, 0x3c040000,
+0x3c020001, 0x8c423408, 0x30420001, 0x10400007, 0x0, 0x3c040000,
0x24846bb4, 0x3c050000, 0x24a570e8, 0x10000006, 0xa42823, 0x3c040000,
0x248466e8, 0x3c050000, 0x24a56bac, 0xa42823, 0x27a60030, 0xc0016be,
-0x27a70034, 0x3c010001, 0xac223378, 0x3c020001, 0x8c423378, 0x3c030800,
+0x27a70034, 0x3c010001, 0xac2234d8, 0x3c020001, 0x8c4234d8, 0x3c030800,
0x21100, 0x21182, 0x431025, 0xae420040, 0x8f830060, 0x74100b,
0x242000a, 0x200f821, 0x0, 0xd, 0x8fbf0060, 0x8fbe005c,
0x8fb50058, 0x8fb30054, 0x8fb10050, 0x3e00008, 0x27bd0068, 0x3e00008,
@@ -3199,69 +3221,69 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x27bdfde0, 0x27a70018, 0x3c02dead, 0x3442beef, 0xafbf0218, 0x8f830150,
0x3c04001f, 0x3484ffff, 0xafa20018, 0xe33823, 0xe43824, 0x8ce30000,
0x10620008, 0x0, 0xafa30010, 0xafa00014, 0x8f860150, 0x3c040001,
-0x24842600, 0xc0028eb, 0x24050020, 0x8fbf0218, 0x3e00008, 0x27bd0220,
+0x24842730, 0xc00290f, 0x24050020, 0x8fbf0218, 0x3e00008, 0x27bd0220,
0x27bdffe0, 0x3c06abba, 0x34c6babe, 0xafb10018, 0x3c110004, 0x3c07007f,
0x34e7ffff, 0xafbf001c, 0x112840, 0x8e240000, 0x8ca30000, 0xaca00000,
0xae260000, 0x8ca20000, 0xaca30000, 0x10460005, 0xae240000, 0xa08821,
-0xf1102b, 0x1040fff5, 0x112840, 0x3c040001, 0x2484260c, 0x2202821,
-0x3021, 0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x2201021,
+0xf1102b, 0x1040fff5, 0x112840, 0x3c040001, 0x2484273c, 0x2202821,
+0x3021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x2201021,
0x8fbf001c, 0x8fb10018, 0x3e00008, 0x27bd0020, 0x27bdffc8, 0xafb30024,
0x809821, 0xafbe002c, 0xafb50028, 0xe0a821, 0x24a50003, 0xafbf0030,
0xafb10020, 0x8ea20000, 0x2403fffc, 0xa38824, 0x51102b, 0x14400020,
0xc0f021, 0x8fc80000, 0xafa00010, 0xafa8001c, 0x8ea20000, 0x3c040001,
-0x24842618, 0xafa20014, 0x8fc60000, 0x2602821, 0xc0028eb, 0x2203821,
+0x24842748, 0xafa20014, 0x8fc60000, 0x2602821, 0xc00290f, 0x2203821,
0x8fc60000, 0x111882, 0x2463ffff, 0x2402ffff, 0x10620008, 0x2602021,
0x2405ffff, 0x8c820000, 0x24840004, 0x2463ffff, 0xacc20000, 0x1465fffb,
0x24c60004, 0x8ea20000, 0x511023, 0xaea20000, 0x8fc20000, 0x511021,
-0x1000000b, 0xafc20000, 0xafa00010, 0x8ea20000, 0x3c040001, 0x24842620,
-0xafa20014, 0x8fc60000, 0x2602821, 0x2203821, 0xc0028eb, 0xafa5001c,
+0x1000000b, 0xafc20000, 0xafa00010, 0x8ea20000, 0x3c040001, 0x24842750,
+0xafa20014, 0x8fc60000, 0x2602821, 0x2203821, 0xc00290f, 0xafa5001c,
0x8fa2001c, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020,
0x3e00008, 0x27bd0038, 0x27bdffe8, 0x3c1cc000, 0xd021, 0x3c05ffff,
-0x3c030001, 0x8c633340, 0x3c040001, 0x8c843348, 0x34a57e10, 0x24021ffc,
-0x3c010001, 0xac2231e0, 0x3c0200c0, 0x3c010001, 0xac2231e4, 0x3c020020,
+0x3c030001, 0x8c6334a0, 0x3c040001, 0x8c8434a8, 0x34a57e10, 0x24021ffc,
+0x3c010001, 0xac223340, 0x3c0200c0, 0x3c010001, 0xac223344, 0x3c020020,
0xafbf0010, 0x3c0100c0, 0xac201ffc, 0x431023, 0x441023, 0x245bb000,
-0x365b821, 0x3c1d0001, 0x8fbd31dc, 0x3a0f021, 0x3c0400c0, 0x34840200,
-0x3c1600c0, 0x3c0300c0, 0x34630758, 0x24021dfc, 0x3c010001, 0xac2231e0,
-0x240218a4, 0x3c010001, 0xac2431e4, 0x3c010001, 0xac2231e0, 0x3c010001,
-0xac2331e4, 0xc00172c, 0x36d60200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
-0x27bdffc8, 0x3c040001, 0x24842628, 0x2821, 0x3c020001, 0x8c4231e0,
-0x3c030001, 0x8c6331e4, 0x3021, 0x3603821, 0xafbf0030, 0xafbe002c,
+0x365b821, 0x3c1d0001, 0x8fbd333c, 0x3a0f021, 0x3c0400c0, 0x34840200,
+0x3c1600c0, 0x3c0300c0, 0x34630758, 0x24021dfc, 0x3c010001, 0xac223340,
+0x240218a4, 0x3c010001, 0xac243344, 0x3c010001, 0xac223340, 0x3c010001,
+0xac233344, 0xc00172c, 0x36d60200, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x27bdffc8, 0x3c040001, 0x24842758, 0x2821, 0x3c020001, 0x8c423340,
+0x3c030001, 0x8c633344, 0x3021, 0x3603821, 0xafbf0030, 0xafbe002c,
0xafb50028, 0xafb30024, 0xafb10020, 0xafa2001c, 0xafa30018, 0xafb70010,
-0xc0028eb, 0xafb60014, 0xc001849, 0x0, 0x8f820240, 0x34420004,
+0xc00290f, 0xafb60014, 0xc001849, 0x0, 0x8f820240, 0x34420004,
0xaf820240, 0x24020001, 0xaec20000, 0x3c020001, 0x571021, 0x904281ec,
-0x10400090, 0x2402fffc, 0x3c110001, 0x2631a33b, 0x3c150001, 0x26b59ee8,
+0x10400090, 0x2402fffc, 0x3c110001, 0x2631a3c3, 0x3c150001, 0x26b59f70,
0x2351823, 0x8fa6001c, 0x628824, 0xd1102b, 0x1440001e, 0x27be0018,
-0x8fb30018, 0x3c040001, 0x24842618, 0x2a02821, 0x2203821, 0xafa00010,
-0xafa60014, 0xc0028eb, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff,
+0x8fb30018, 0x3c040001, 0x24842748, 0x2a02821, 0x2203821, 0xafa00010,
+0xafa60014, 0xc00290f, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff,
0x2402ffff, 0x10620008, 0x2a02821, 0x2406ffff, 0x8ca20000, 0x24a50004,
0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x511023,
0xafa2001c, 0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001,
-0x24842620, 0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821,
-0xc0028eb, 0xa09821, 0x8fa3001c, 0x24150020, 0x3c010001, 0xac33335c,
-0x2c620020, 0x1440001d, 0x27b30018, 0x8fb10018, 0x3c040001, 0x24842618,
-0x3c050001, 0x24a533f0, 0x24070020, 0xafa00010, 0xafa30014, 0xc0028eb,
-0x2203021, 0x3c050001, 0x24a533f0, 0x8fa40018, 0x24030007, 0x2406ffff,
+0x24842750, 0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821,
+0xc00290f, 0xa09821, 0x8fa3001c, 0x24150020, 0x3c010001, 0xac3334bc,
+0x2c620020, 0x1440001d, 0x27b30018, 0x8fb10018, 0x3c040001, 0x24842748,
+0x3c050001, 0x24a53550, 0x24070020, 0xafa00010, 0xafa30014, 0xc00290f,
+0x2203021, 0x3c050001, 0x24a53550, 0x8fa40018, 0x24030007, 0x2406ffff,
0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004,
0x8fa2001c, 0x551023, 0xafa2001c, 0x8e620000, 0x551021, 0x1000000c,
-0xae620000, 0x3c040001, 0x24842620, 0x3c050001, 0x24a533f0, 0xafa00010,
-0xafa30014, 0x8fa60018, 0x3c110001, 0x263133f0, 0xc0028eb, 0x24070020,
-0x8fa3001c, 0x24150020, 0x3c010001, 0xac313390, 0x2c620020, 0x1440001d,
-0x27b30018, 0x8fb10018, 0x3c040001, 0x24842618, 0x3c050001, 0x24a53410,
-0x24070020, 0xafa00010, 0xafa30014, 0xc0028eb, 0x2203021, 0x3c050001,
-0x24a53410, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004,
+0xae620000, 0x3c040001, 0x24842750, 0x3c050001, 0x24a53550, 0xafa00010,
+0xafa30014, 0x8fa60018, 0x3c110001, 0x26313550, 0xc00290f, 0x24070020,
+0x8fa3001c, 0x24150020, 0x3c010001, 0xac3134f0, 0x2c620020, 0x1440001d,
+0x27b30018, 0x8fb10018, 0x3c040001, 0x24842748, 0x3c050001, 0x24a53570,
+0x24070020, 0xafa00010, 0xafa30014, 0xc00290f, 0x2203021, 0x3c050001,
+0x24a53570, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004,
0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x551023,
0xafa2001c, 0x8e620000, 0x551021, 0x1000000c, 0xae620000, 0x3c040001,
-0x24842620, 0x3c050001, 0x24a53410, 0xafa00010, 0xafa30014, 0x8fa60018,
-0x3c110001, 0x26313410, 0xc0028eb, 0x24070020, 0x3c010001, 0x10000033,
-0xac31338c, 0x3c110000, 0x26317cef, 0x3c150000, 0x26b57b3c, 0x2351823,
+0x24842750, 0x3c050001, 0x24a53570, 0xafa00010, 0xafa30014, 0x8fa60018,
+0x3c110001, 0x26313570, 0xc00290f, 0x24070020, 0x3c010001, 0x10000033,
+0xac3134ec, 0x3c110000, 0x26317cef, 0x3c150000, 0x26b57b3c, 0x2351823,
0x8fa6001c, 0x628824, 0xd1102b, 0x1440001e, 0x27be0018, 0x8fb30018,
-0x3c040001, 0x24842618, 0x2a02821, 0x2203821, 0xafa00010, 0xafa60014,
-0xc0028eb, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff,
+0x3c040001, 0x24842748, 0x2a02821, 0x2203821, 0xafa00010, 0xafa60014,
+0xc00290f, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff,
0x10620008, 0x2a02821, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff,
0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x511023, 0xafa2001c,
-0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 0x24842620,
-0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 0xc0028eb,
-0xa09821, 0x3c010001, 0xac33335c, 0x3c030001, 0x8c63335c, 0x24020400,
+0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 0x24842750,
+0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 0xc00290f,
+0xa09821, 0x3c010001, 0xac3334bc, 0x3c030001, 0x8c6334bc, 0x24020400,
0x60f809, 0xaf820070, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024,
0x8fb10020, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x0,
0x8f820040, 0x3c03f000, 0x431824, 0x3c025000, 0x10620005, 0x3c026000,
@@ -3272,13 +3294,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8f820054, 0x244203e8, 0xaf820058, 0x240201f4, 0xaec200c8, 0x24020004,
0xaec200d0, 0x24020002, 0xaec000a0, 0xaec000cc, 0xaec200c4, 0xaec000c0,
0xaec000bc, 0x3e00008, 0xaec000b8, 0x8f820054, 0x24420005, 0x3e00008,
-0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x3c030001, 0x8c6332bc,
-0x244203e8, 0x1060001d, 0xaf820058, 0x3c020001, 0x8c4232a8, 0x30420001,
-0x1440000c, 0x0, 0x3c020001, 0x8c4233c8, 0x10400008, 0x0,
-0x8f830224, 0x3c020001, 0x8c42548c, 0x10620003, 0x0, 0xc003a65,
+0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x3c030001, 0x8c63341c,
+0x244203e8, 0x1060001d, 0xaf820058, 0x3c020001, 0x8c423408, 0x30420001,
+0x1440000c, 0x0, 0x3c020001, 0x8c423528, 0x10400008, 0x0,
+0x8f830224, 0x3c020001, 0x8c4255ec, 0x10620003, 0x0, 0xc003ab1,
0x0, 0x92c200ec, 0x10400003, 0x3c0208ff, 0x1000000a, 0xa2c000ec,
0x3442fffb, 0x8f830220, 0x3c040200, 0x284a025, 0x621824, 0x10000003,
-0xaf830220, 0xc003d6d, 0x0, 0x8f420238, 0x1040000a, 0x0,
+0xaf830220, 0xc003db9, 0x0, 0x8f420238, 0x1040000a, 0x0,
0x8ec200a0, 0x244203e8, 0xaec200a0, 0x8f430238, 0x43102b, 0x14400003,
0x0, 0xc001c3c, 0x0, 0x8f420218, 0x30420100, 0x10400003,
0x0, 0xc001e07, 0x0, 0x8ec200c0, 0x8ec300c4, 0x24420001,
@@ -3297,14 +3319,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x3c020001, 0x571021, 0x8c4281d4, 0x10400023, 0x24070008, 0x8ed10018,
0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010,
0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b,
-0x24020001, 0x3c040001, 0x24842690, 0xafb10010, 0xafa00014, 0x8ec6002c,
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400005,
+0x24020001, 0x3c040001, 0x248427c0, 0xafb10010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400005,
0x24020001, 0x3c010001, 0x370821, 0x1000005c, 0xac2281d4, 0x3c010001,
0x370821, 0x10000022, 0xac2081d0, 0x8ed10018, 0x8ee40498, 0x8ee5049c,
0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018,
0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001,
-0x24842690, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
-0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001,
+0x248427c0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
+0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001,
0x370821, 0x1000003a, 0xac2281d8, 0x3c010001, 0x370821, 0xac2281d0,
0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4,
0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 0x1000002a,
@@ -3323,8 +3345,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xafbf0024, 0xafb10020, 0x8ec30068, 0x8ec2006c, 0x10620029, 0x24070008,
0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013,
0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c,
-0x1440000b, 0x24020001, 0x3c040001, 0x2484269c, 0xafb10010, 0xafa00014,
-0x8ec60068, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f008, 0x1021,
+0x1440000b, 0x24020001, 0x3c040001, 0x248427cc, 0xafb10010, 0xafa00014,
+0x8ec60068, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021,
0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000000e, 0xac2281e0,
0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c,
0x24420001, 0xaec20268, 0x10000004, 0x8ec20268, 0x3c010001, 0x370821,
@@ -3333,15 +3355,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 0xaf820060,
0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048,
0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
-0x3c020001, 0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030,
+0x3c020001, 0x8c42341c, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030,
0xafb3002c, 0x104000fe, 0xafb10028, 0x8ec200b8, 0x24430001, 0x2842000b,
0x1440011b, 0xaec300b8, 0xaec000b8, 0x8ee204a8, 0x30420002, 0x14400096,
-0x0, 0x8ee204a8, 0x3c030001, 0x8c6332ac, 0x34420002, 0xaee204a8,
+0x0, 0x8ee204a8, 0x3c030001, 0x8c63340c, 0x34420002, 0xaee204a8,
0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000,
0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c,
0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 0x0,
-0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
-0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0,
+0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
+0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0,
0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000,
0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8,
0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000c, 0x8ec8002c,
@@ -3350,7 +3372,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0,
0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023,
0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 0xaed3002c,
-0x3c040001, 0x248426d4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
+0x3c040001, 0x24842804, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001,
0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054, 0x8f820054,
0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 0xa821, 0x3c1e0020,
@@ -3358,8 +3380,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8, 0x24070008,
0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054, 0x2221023,
0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 0x1440000f, 0x0,
-0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
-0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, 0x8ec202d0, 0x24420001,
+0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
+0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001,
0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250, 0x8ec20250,
0x8ee204a8, 0x30420001, 0x10400054, 0x0, 0x8f420218, 0x30420080,
0x1040002b, 0x0, 0x8f820044, 0x34420040, 0xaf820044, 0x8ec200b0,
@@ -3384,15 +3406,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x24430001, 0x284201f5, 0x14400005, 0xaec300bc, 0x8f820044, 0x38420020,
0xaf820044, 0xaec000bc, 0x2402ff7f, 0x282a024, 0x8fbf0038, 0x8fbe0034,
0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3e00008,
-0x0, 0x3c020001, 0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034,
+0x0, 0x3c020001, 0x8c42341c, 0x27bdffc0, 0xafbf0038, 0xafbe0034,
0xafb50030, 0xafb3002c, 0x10400100, 0xafb10028, 0x8ec200b8, 0x3c040001,
-0x8c8432ac, 0x24430001, 0x2842000b, 0xaec400d0, 0x14400127, 0xaec300b8,
+0x8c84340c, 0x24430001, 0x2842000b, 0xaec400d0, 0x14400127, 0xaec300b8,
0xaec000b8, 0x8ee204a8, 0x30420002, 0x14400094, 0x0, 0x8ee204a8,
0x34420002, 0xaee204a8, 0x24020001, 0x14820003, 0x3c020600, 0x10000002,
0x34423000, 0x34421000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004,
0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228,
-0x1662000f, 0x0, 0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014,
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0,
+0x1662000f, 0x0, 0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014,
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0,
0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0,
0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054,
0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821,
@@ -3401,7 +3423,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018,
0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001,
0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff,
-0x54400011, 0xaed3002c, 0x3c040001, 0x248426d4, 0xafa00010, 0xafa00014,
+0x54400011, 0xaed3002c, 0x3c040001, 0x24842804, 0xafa00010, 0xafa00014,
0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c,
0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff,
0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017,
@@ -3409,35 +3431,35 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ec3002c, 0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018,
0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0,
0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff,
-0x1440000f, 0x0, 0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 0x0,
+0x1440000f, 0x0, 0x3c040001, 0x24842810, 0xafa00010, 0xafa00014,
+0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0,
0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001,
0xaec20250, 0x8ec20250, 0x8ee204a8, 0x30420001, 0x10400055, 0x0,
0x8f420218, 0x30420080, 0x10400027, 0x0, 0x8ec200b0, 0x3c040001,
-0x90843370, 0x24080000, 0x2409ffff, 0x403821, 0x8ec201b8, 0x8ec301bc,
-0x3021, 0x34840020, 0x3c010001, 0xa0243370, 0x481024, 0x1446000d,
+0x908434d0, 0x24080000, 0x2409ffff, 0x403821, 0x8ec201b8, 0x8ec301bc,
+0x3021, 0x34840020, 0x3c010001, 0xa02434d0, 0x481024, 0x1446000d,
0x691824, 0x1467000b, 0x0, 0x8ec200b4, 0x403821, 0x8ec201d8,
0x8ec301dc, 0x3021, 0x481024, 0x14460003, 0x691824, 0x10670009,
-0x308200bf, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 0x90843370, 0x8ec601d8,
-0x8ec701dc, 0x10000026, 0x38840040, 0x3c010001, 0x10000061, 0xa0223370,
-0x8ec200b0, 0x3c040001, 0x90843370, 0x24080000, 0x2409ffff, 0x403821,
-0x8ec201b8, 0x8ec301bc, 0x3021, 0x308400bf, 0x3c010001, 0xa0243370,
+0x308200bf, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 0x908434d0, 0x8ec601d8,
+0x8ec701dc, 0x10000026, 0x38840040, 0x3c010001, 0x10000061, 0xa02234d0,
+0x8ec200b0, 0x3c040001, 0x908434d0, 0x24080000, 0x2409ffff, 0x403821,
+0x8ec201b8, 0x8ec301bc, 0x3021, 0x308400bf, 0x3c010001, 0xa02434d0,
0x481024, 0x1446000d, 0x691824, 0x1467000b, 0x0, 0x8ec200b4,
0x403821, 0x8ec201d8, 0x8ec301dc, 0x3021, 0x481024, 0x14460003,
0x691824, 0x1067000d, 0x34820020, 0x8ec201b8, 0x8ec301bc, 0x3c040001,
-0x90843370, 0x8ec601d8, 0x8ec701dc, 0x38840020, 0xaec300b0, 0xaec700b4,
-0x3c010001, 0x1000003a, 0xa0243370, 0x3c010001, 0x10000037, 0xa0223370,
-0x3c020001, 0x90423370, 0x8ec300bc, 0x34440020, 0x24620001, 0x10000028,
+0x908434d0, 0x8ec601d8, 0x8ec701dc, 0x38840020, 0xaec300b0, 0xaec700b4,
+0x3c010001, 0x1000003a, 0xa02434d0, 0x3c010001, 0x10000037, 0xa02234d0,
+0x3c020001, 0x904234d0, 0x8ec300bc, 0x34440020, 0x24620001, 0x10000028,
0x28630033, 0x8ec200cc, 0x8ec300c8, 0x24420001, 0xaec200cc, 0x43102a,
0x14400006, 0x24030001, 0x8ec200d0, 0x14430002, 0xaec000cc, 0x24030004,
0xaec300d0, 0x8ee204a8, 0x30420001, 0x10400012, 0x0, 0x8f420218,
-0x30420080, 0x10400008, 0x0, 0x3c020001, 0x90423370, 0x34420040,
-0x304200df, 0x3c010001, 0x10000015, 0xa0223370, 0x3c020001, 0x90423370,
-0x34420060, 0x3c010001, 0x1000000f, 0xa0223370, 0x3c020001, 0x90423370,
-0x8ec300bc, 0x34440020, 0x24620001, 0x286300fb, 0x3c010001, 0xa0243370,
-0x14600005, 0xaec200bc, 0x38820040, 0x3c010001, 0xa0223370, 0xaec000bc,
-0x3c020001, 0x90423370, 0x8ec300d0, 0x3044007f, 0x24020001, 0x3c010001,
-0xa0243370, 0x54620003, 0x3484000f, 0x42102, 0x348400f0, 0xc004904,
+0x30420080, 0x10400008, 0x0, 0x3c020001, 0x904234d0, 0x34420040,
+0x304200df, 0x3c010001, 0x10000015, 0xa02234d0, 0x3c020001, 0x904234d0,
+0x34420060, 0x3c010001, 0x1000000f, 0xa02234d0, 0x3c020001, 0x904234d0,
+0x8ec300bc, 0x34440020, 0x24620001, 0x286300fb, 0x3c010001, 0xa02434d0,
+0x14600005, 0xaec200bc, 0x38820040, 0x3c010001, 0xa02234d0, 0xaec000bc,
+0x3c020001, 0x904234d0, 0x8ec300d0, 0x3044007f, 0x24020001, 0x3c010001,
+0xa02434d0, 0x54620003, 0x3484000f, 0x42102, 0x348400f0, 0xc004950,
0x0, 0x2402ff7f, 0x282a024, 0x8fbf0038, 0x8fbe0034, 0x8fb50030,
0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3e00008, 0x0,
0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0xafb10028,
@@ -3477,7 +3499,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ec200a8, 0x26e60028, 0x40f809, 0x24070400, 0x104000f1, 0x3c020400,
0xafa20020, 0x92c20115, 0x10400080, 0x240200ff, 0x8ec3002c, 0x10620004,
0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228,
-0x1662000a, 0x0, 0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014,
+0x1662000a, 0x0, 0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014,
0x8ec6002c, 0x8f470228, 0x3c050009, 0x1000007f, 0x34a5f00f, 0x8ec2002c,
0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4,
0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e,
@@ -3486,8 +3508,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0,
0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006,
0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0,
-0x32a200ff, 0x54400018, 0xaed3002c, 0x3c040001, 0x248426d4, 0xafa00010,
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f010, 0xc0028eb,
+0x32a200ff, 0x54400018, 0xaed3002c, 0x3c040001, 0x24842804, 0xafa00010,
+0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f010, 0xc00290f,
0x0, 0x8ec202d0, 0x1821, 0x24420001, 0xaec202d0, 0x1000008f,
0x8ec202d0, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c,
0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023,
@@ -3495,23 +3517,23 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018,
0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0,
0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff,
-0x1440006a, 0x24030001, 0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014,
+0x1440006a, 0x24030001, 0x3c040001, 0x24842810, 0xafa00010, 0xafa00014,
0x8f860120, 0x8f870124, 0x3c050009, 0x1000ffcb, 0x34a5f011, 0x8ec3002c,
0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001, 0x8821,
-0x8f420228, 0x16220011, 0x4021, 0x3c040001, 0x248426a8, 0xafa00010,
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc0028eb,
+0x8f420228, 0x16220011, 0x4021, 0x3c040001, 0x248427d8, 0xafa00010,
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc00290f,
0x0, 0x8ec202a0, 0x1821, 0x24420001, 0xaec202a0, 0x10000047,
0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004,
0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c,
0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0,
0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0,
0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c,
-0xaed1002c, 0x3c040001, 0x248426b4, 0xafa00010, 0xafa00014, 0x8ec6002c,
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001e, 0x1821,
+0xaed1002c, 0x3c040001, 0x248427e4, 0xafa00010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001e, 0x1821,
0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011,
0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440000f, 0x24030001, 0x3c040001, 0x248426bc, 0xafa00010,
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001,
+0x24c6001c, 0x1440000f, 0x24030001, 0x3c040001, 0x248427ec, 0xafa00010,
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001,
0x8ec202a4, 0x1821, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x1060000d,
0x24020001, 0x8ec2024c, 0xa2c00115, 0xaec000a0, 0x24420001, 0xaec2024c,
0x8ec2024c, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x10000003, 0x8ee2014c,
@@ -3524,15 +3546,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8f8200b0, 0x2403fffb, 0x431024, 0xaf8200b0, 0x8f82011c, 0x2403fffd,
0x431024, 0x10000040, 0xaf82011c, 0x8ec30104, 0x8f820104, 0x14620005,
0x0, 0x8ec3010c, 0x8f8200b4, 0x5062000a, 0x3c050005, 0x8f820104,
-0xaec20104, 0x8f8200b4, 0xaec2010c, 0x8ec2010c, 0x3c040001, 0x248426ec,
-0x10000029, 0xafa00014, 0x8ec2010c, 0x3c040001, 0x248426f8, 0xafa00014,
-0xafa20010, 0x8f8600b0, 0x8ec70104, 0xc0028eb, 0x34a50900, 0x8f82011c,
+0xaec20104, 0x8f8200b4, 0xaec2010c, 0x8ec2010c, 0x3c040001, 0x2484281c,
+0x10000029, 0xafa00014, 0x8ec2010c, 0x3c040001, 0x24842828, 0xafa00014,
+0xafa20010, 0x8f8600b0, 0x8ec70104, 0xc00290f, 0x34a50900, 0x8f82011c,
0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0,
0xaf830104, 0x8f440208, 0x8f45020c, 0x2402000f, 0xafa20010, 0xafa00014,
0x8ec20008, 0xafa20018, 0x8ec200a8, 0x26e60028, 0x40f809, 0x24070400,
0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201cc, 0x24420001,
-0xaee201cc, 0x8ee201cc, 0x8ec2010c, 0x3c040001, 0x24842704, 0xafa00014,
-0xafa20010, 0x8f8600b0, 0x8ec70104, 0x3c050005, 0xc0028eb, 0x34a50900,
+0xaee201cc, 0x8ee201cc, 0x8ec2010c, 0x3c040001, 0x24842834, 0xafa00014,
+0xafa20010, 0x8f8600b0, 0x8ec70104, 0x3c050005, 0xc00290f, 0x34a50900,
0x8f8200a0, 0x30420004, 0x1040005f, 0x0, 0x8ec30108, 0x8f820124,
0x14620005, 0x0, 0x8ec30110, 0x8f8200a4, 0x10620006, 0x0,
0x8f820124, 0xaec20108, 0x8f8200a4, 0x10000052, 0xaec20110, 0x8f8200a0,
@@ -3541,15 +3563,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x2403fffd, 0x431024, 0x10000041, 0xaf82011c, 0x8ec30108, 0x8f820124,
0x14620005, 0x0, 0x8ec30110, 0x8f8200a4, 0x5062000a, 0x3c050005,
0x8f820124, 0xaec20108, 0x8f8200a4, 0xaec20110, 0x8ec20110, 0x3c040001,
-0x24842710, 0x1000002a, 0xafa00014, 0x8ec20110, 0x3c040001, 0x2484271c,
-0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0xc0028eb, 0x34a50900,
+0x24842840, 0x1000002a, 0xafa00014, 0x8ec20110, 0x3c040001, 0x2484284c,
+0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0xc00290f, 0x34a50900,
0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001,
0xaf8200a0, 0xaf830124, 0x8f440208, 0x8f45020c, 0x24020010, 0xafa20010,
-0xafa00014, 0x8ec20010, 0xafa20018, 0x8ec200a4, 0x3c060001, 0x24c63384,
+0xafa00014, 0x8ec20010, 0xafa20018, 0x8ec200a4, 0x3c060001, 0x24c634e4,
0x40f809, 0x24070004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c,
0x8ee201cc, 0x24420001, 0xaee201cc, 0x8ee201cc, 0x8ec20110, 0x3c040001,
-0x24842728, 0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0x3c050005,
-0xc0028eb, 0x34a50900, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c091000,
+0x24842858, 0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0x3c050005,
+0xc00290f, 0x34a50900, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c091000,
0x24080001, 0x3c070080, 0x3c050100, 0x3c062000, 0x8f820070, 0x491024,
0x1040fffd, 0x0, 0x8f820054, 0x24420005, 0xaf820078, 0x8f420234,
0x10400017, 0x2021, 0x3c020001, 0x571021, 0x8c4281dc, 0x24420005,
@@ -3576,7 +3598,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8ec20260, 0x24420001,
0xaec20260, 0x1000006f, 0x8ec20260, 0x30c20001, 0x10400004, 0x24020001,
0xaf820064, 0x10000069, 0x0, 0x30c20002, 0x1440000b, 0x3c050003,
-0x3c040001, 0x24842800, 0x34a50001, 0x3821, 0xafa00010, 0xc0028eb,
+0x3c040001, 0x24842930, 0x34a50001, 0x3821, 0xafa00010, 0xc00290f,
0xafa00014, 0x2402fff8, 0x1000005c, 0xaf820064, 0x8f43022c, 0x8f42010c,
0x1062004c, 0x0, 0x8f42022c, 0x21080, 0x5a1021, 0x8c440300,
0x8f42022c, 0x24420001, 0x3042003f, 0x41e02, 0xaf42022c, 0x24020003,
@@ -3596,15 +3618,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x3e00008, 0x27bd0020, 0x3e00008, 0x0, 0x27bdffc0, 0xafb10028,
0x808821, 0x111602, 0x2442ffff, 0x304300ff, 0x2c620011, 0xafbf0038,
0xafbe0034, 0xafb50030, 0x104001ab, 0xafb3002c, 0x31080, 0x3c010001,
-0x220821, 0x8c222848, 0x400008, 0x0, 0x111302, 0x30440fff,
+0x220821, 0x8c222978, 0x400008, 0x0, 0x111302, 0x30440fff,
0x24020001, 0x10820006, 0x3c030800, 0x24020002, 0x1082000c, 0x3c050003,
-0x10000022, 0x0, 0x3c020001, 0x8c4233b4, 0x21100, 0x21182,
+0x10000022, 0x0, 0x3c020001, 0x8c423514, 0x21100, 0x21182,
0x431025, 0xae420038, 0x8ee204a8, 0x1000000a, 0x34420001, 0x3c020001,
-0x2442c440, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8,
+0x2442c4d0, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8,
0x2403fffe, 0x431024, 0xaee204a8, 0xaec40168, 0xaec4016c, 0x8f840054,
0x41442, 0x41c82, 0x431021, 0x41cc2, 0x431023, 0x41d02,
0x431021, 0x41d42, 0x431023, 0x10000009, 0xaec20170, 0x3c040001,
-0x2484280c, 0x34a50004, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb,
+0x2484293c, 0x34a50004, 0x2203021, 0x3821, 0xafa00010, 0xc00290f,
0xafa00014, 0x8ec20208, 0x24420001, 0xaec20208, 0x100001e1, 0x8ec20208,
0xc0022fe, 0x0, 0x100001dd, 0x0, 0xc002419, 0x0,
0x100001d9, 0x0, 0x111302, 0x30430fff, 0x24020001, 0x10620005,
@@ -3614,24 +3636,24 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xaf82022c, 0xaf820230, 0xaf820234, 0x24020001, 0x10000016, 0xa2c2011c,
0x92c2011c, 0x50400013, 0xa2c0011c, 0x8ee204ac, 0xaf820228, 0x8ee204b0,
0xaf82022c, 0x8ee204b4, 0xaf820230, 0x8ee204b8, 0xaf820234, 0x10000009,
-0xa2c0011c, 0x3c040001, 0x24842818, 0x34a5f009, 0x2203021, 0x3821,
-0xafa00010, 0xc0028eb, 0xafa00014, 0x8ec20234, 0x24420001, 0xaec20234,
+0xa2c0011c, 0x3c040001, 0x24842948, 0x34a5f009, 0x2203021, 0x3821,
+0xafa00010, 0xc00290f, 0xafa00014, 0x8ec20234, 0x24420001, 0xaec20234,
0x100001a3, 0x8ec20234, 0x111302, 0x30440fff, 0x24020001, 0x10820005,
0x24020002, 0x1082000d, 0x3c050003, 0x10000013, 0x0, 0x8f820220,
0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001,
0xa2c2011d, 0x10000011, 0xaec40200, 0x8f820220, 0x3c0308ff, 0x3463fff7,
0x431024, 0xaf820220, 0xa2c0011d, 0x10000009, 0xaec40200, 0x3c040001,
-0x24842824, 0x34a5f00a, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb,
+0x24842954, 0x34a5f00a, 0x2203021, 0x3821, 0xafa00010, 0xc00290f,
0xafa00014, 0x8ec20224, 0x24420001, 0xaec20224, 0x1000017b, 0x8ec20224,
-0x27840208, 0x27450200, 0xc00297e, 0x24060008, 0x26c4018c, 0x27450200,
-0xc00297e, 0x24060008, 0x8ec2022c, 0x24420001, 0xaec2022c, 0x1000016e,
+0x27840208, 0x27450200, 0xc0029a2, 0x24060008, 0x26c4018c, 0x27450200,
+0xc0029a2, 0x24060008, 0x8ec2022c, 0x24420001, 0xaec2022c, 0x1000016e,
0x8ec2022c, 0x111302, 0x30430fff, 0x24020001, 0x10620011, 0x28620002,
0x50400005, 0x24020002, 0x10600007, 0x0, 0x10000017, 0x0,
0x1062000f, 0x0, 0x10000013, 0x0, 0x8f460248, 0x24040001,
-0xc004680, 0x24050004, 0x10000007, 0x0, 0x8f460248, 0x24040001,
-0xc004680, 0x24050004, 0x10000010, 0x0, 0x8f46024c, 0x24040001,
-0xc004680, 0x24050001, 0x1000000a, 0x0, 0x3c040001, 0x24842830,
-0x3c050003, 0x34a50005, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb,
+0xc0046cc, 0x24050004, 0x10000007, 0x0, 0x8f460248, 0x24040001,
+0xc0046cc, 0x24050004, 0x10000010, 0x0, 0x8f46024c, 0x24040001,
+0xc0046cc, 0x24050001, 0x1000000a, 0x0, 0x3c040001, 0x24842960,
+0x3c050003, 0x34a50005, 0x2203021, 0x3821, 0xafa00010, 0xc00290f,
0xafa00014, 0x8ec20228, 0x24420001, 0xaec20228, 0x1000013f, 0x8ec20228,
0xc002221, 0x0, 0x1000013b, 0x0, 0x24020001, 0xa2c20528,
0x24110014, 0x8ee404a0, 0x8ee504a4, 0xafb10010, 0xafa00014, 0x8ec20010,
@@ -3639,8 +3661,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x1000012a, 0x0, 0x3c020900, 0xaec00054, 0xaec00058,
0xaec0005c, 0xaec00060, 0xaec002c0, 0xa2c00065, 0xafa20020, 0x8ec3002c,
0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001,
-0x9821, 0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x248427dc,
-0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb,
+0x9821, 0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x2484290c,
+0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f,
0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006b, 0x8ec202a0,
0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0,
0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
@@ -3649,7 +3671,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x1021, 0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021,
0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021,
0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5,
-0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x248427e8,
+0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x24842918,
0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x1000002e,
0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c,
0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023,
@@ -3657,33 +3679,33 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018,
0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0,
0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff,
-0x1440000f, 0x0, 0x3c040001, 0x248427f4, 0xafa00010, 0xafa00014,
-0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 0x0,
+0x1440000f, 0x0, 0x3c040001, 0x24842924, 0xafa00010, 0xafa00014,
+0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0,
0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20218, 0x24420001,
0xaec20218, 0x8ec20218, 0x8ec2025c, 0x24420001, 0xaec2025c, 0x10000096,
0x8ec2025c, 0x8f42025c, 0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200,
-0x24060008, 0xc00297e, 0xaec20160, 0x8f820220, 0x30420008, 0x14400002,
+0x24060008, 0xc0029a2, 0xaec20160, 0x8f820220, 0x30420008, 0x14400002,
0x24020001, 0x24020002, 0xaec20200, 0x8ec20214, 0x24420001, 0xaec20214,
0x10000083, 0x8ec20214, 0x3c0200ff, 0x96e30462, 0x3442ffff, 0x2222024,
0x3402fffb, 0x44102b, 0x38420001, 0x30630003, 0x2c630001, 0x621824,
-0x10600003, 0x0, 0x10000075, 0xaec40050, 0x3c040001, 0x2484283c,
-0x3c050003, 0x34a5f00f, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb,
+0x10600003, 0x0, 0x10000075, 0xaec40050, 0x3c040001, 0x2484296c,
+0x3c050003, 0x34a5f00f, 0x2203021, 0x3821, 0xafa00010, 0xc00290f,
0xafa00014, 0x3c030700, 0x34631000, 0x111602, 0x431025, 0xafa20020,
0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002,
0x24510001, 0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001,
-0x248427bc, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
-0xc0028eb, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046,
+0x248428ec, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
+0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046,
0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004,
0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c,
0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0,
0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0,
0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c,
-0xaed1002c, 0x3c040001, 0x248427c8, 0xafa00010, 0xafa00014, 0x8ec6002c,
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 0x0,
+0xaed1002c, 0x3c040001, 0x248428f8, 0xafa00010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0,
0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011,
0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809,
-0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x248427d0, 0xafa00010,
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001,
+0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842900, 0xafa00010,
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001,
0x8ec202a4, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x8ec20244, 0x24420001,
0xaec20244, 0x8ec20244, 0x8ec20254, 0x24420001, 0xaec20254, 0x8ec20254,
0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008,
@@ -3697,16 +3719,16 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xaf820220, 0x8f820200, 0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004,
0xaf820200, 0x8ede02bc, 0x8ec702c0, 0xafa70014, 0x8ec702c4, 0xafa7001c,
0x8ec20238, 0x26c40128, 0x24420001, 0xaec20238, 0x8ed10238, 0x8ed3016c,
-0x8ed50168, 0xc00296c, 0x24050400, 0xaede02bc, 0x8fa70014, 0xaec702c0,
+0x8ed50168, 0xc002990, 0x24050400, 0xaede02bc, 0x8fa70014, 0xaec702c0,
0x8fa7001c, 0xaec702c4, 0xaed10238, 0xaed3016c, 0xaed50168, 0x8f42025c,
0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xaec20160,
-0x24020006, 0xc00297e, 0xaec2015c, 0x3c023b9a, 0x3442ca00, 0xaec20164,
+0x24020006, 0xc0029a2, 0xaec2015c, 0x3c023b9a, 0x3442ca00, 0xaec20164,
0x240203e8, 0x24040002, 0x24030001, 0xaec201fc, 0xaec401f8, 0xaec30204,
0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaec30200, 0x10000003,
-0x3021, 0xaec40200, 0x3021, 0x3c030001, 0x661821, 0x90633200,
+0x3021, 0xaec40200, 0x3021, 0x3c030001, 0x661821, 0x90633360,
0x2c61021, 0x24c60001, 0xa0430194, 0x2cc2000f, 0x1440fff8, 0x2c61821,
0x24c60001, 0x8f820040, 0x27440080, 0x24050080, 0x21702, 0x24420030,
-0xa0620194, 0x2c61021, 0xc00296c, 0xa0400194, 0x8fa70024, 0x30e20004,
+0xa0620194, 0x2c61021, 0xc002990, 0xa0400194, 0x8fa70024, 0x30e20004,
0x14400006, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024,
0xaf820220, 0x8fa7002c, 0x30e20004, 0x14400006, 0x0, 0x8f820200,
0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, 0x8fbf0040, 0x8fbe003c,
@@ -3736,11 +3758,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x431026, 0x2c460001, 0xc01021, 0x14400005, 0x510c0, 0x2e21021,
0x944575c0, 0x14a0ffed, 0x510c0, 0xa03021, 0x10c00010, 0x610c0,
0x571821, 0x8c6375c0, 0x571021, 0xafa30010, 0x8c4275c4, 0x3c040001,
-0x2484294c, 0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc0028eb,
+0x24842a7c, 0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc00290f,
0x34a5f012, 0x10000051, 0x3c020800, 0x8ec50124, 0x10a00004, 0x510c0,
0x2e21021, 0x944275c0, 0xaec20124, 0xa03021, 0x14c0000f, 0x27440212,
-0x810c0, 0x2e21021, 0xafa80010, 0x944271c0, 0x3c040001, 0x24842958,
-0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc0028eb, 0x34a5f013,
+0x810c0, 0x2e21021, 0xafa80010, 0x944271c0, 0x3c040001, 0x24842a88,
+0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc00290f, 0x34a5f013,
0x1000003a, 0x3c020800, 0x628c0, 0x94830000, 0xb71021, 0x244275c2,
0xa4430000, 0x8c830002, 0x820c0, 0xac430002, 0x2e41021, 0x944371c0,
0x2e51021, 0xa44375c0, 0x2e41021, 0xa44671c0, 0x8ec20120, 0x24420001,
@@ -3753,8 +3775,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x24020001, 0x821004, 0x621825, 0xaca30228, 0x3c020800, 0x34421000,
0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c,
0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 0x0,
-0x3c040001, 0x24842928, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
-0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0,
+0x3c040001, 0x24842a58, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228,
+0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0,
0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000,
0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8,
0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000d, 0x8ec8002c,
@@ -3763,16 +3785,16 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0,
0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023,
0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 0xaed3002c,
-0x3c040001, 0x24842934, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
+0x3c040001, 0x24842a64, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124,
0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001,
0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054,
0x247103e8, 0x2221023, 0x2c4203e9, 0x10400015, 0xa821, 0x24130011,
0x8ec30008, 0x8ee40488, 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010,
0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c,
0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee,
-0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842940,
+0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842a70,
0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011,
-0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0,
+0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0,
0x8ec2021c, 0x24420001, 0xaec2021c, 0x8ec2021c, 0x8ec20258, 0x24420001,
0xaec20258, 0x8ec20258, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c,
0x8fb10028, 0x3e00008, 0x27bd0040, 0x27bdffb0, 0x27440212, 0x24050006,
@@ -3783,8 +3805,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x94a20004, 0x95230004, 0x431026, 0x2c460001, 0xc01021, 0x14400006,
0x710c0, 0xe04021, 0x2e21021, 0x944775c0, 0x14e0ffec, 0x710c0,
0xe02821, 0x14a0000f, 0xafa80028, 0x410c0, 0x2e21021, 0xafa40010,
-0x944271c0, 0x3c040001, 0x24842964, 0xafa20014, 0x8f460210, 0x8f470214,
-0x3c050003, 0xc0028eb, 0x34a5f01c, 0x10000062, 0x3c020800, 0x11000007,
+0x944271c0, 0x3c040001, 0x24842a94, 0xafa20014, 0x8f460210, 0x8f470214,
+0x3c050003, 0xc00290f, 0x34a5f01c, 0x10000062, 0x3c020800, 0x11000007,
0x510c0, 0x2e21021, 0x944375c0, 0x810c0, 0x2e21021, 0x10000006,
0xa44375c0, 0x2e21021, 0x944375c0, 0x410c0, 0x2e21021, 0xa44371c0,
0x8ec30124, 0x510c0, 0x2e21021, 0x26e871c0, 0xa44375c0, 0x8ec20120,
@@ -3803,8 +3825,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8c420228, 0x831804, 0x31827, 0x431024, 0xaca20228, 0x3c020800,
0x34422000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020,
0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f,
-0x0, 0x3c040001, 0x24842928, 0xafa00010, 0xafa00014, 0x8ec6002c,
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001,
+0x0, 0x3c040001, 0x24842a58, 0xafa00010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001,
0xaec202a0, 0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021,
0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000d,
@@ -3813,7 +3835,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8,
0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054,
0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011,
-0xaed3002c, 0x3c040001, 0x24842934, 0xafa00010, 0xafa00014, 0x8f860120,
+0xaed3002c, 0x3c040001, 0x24842a64, 0xafa00010, 0xafa00014, 0x8f860120,
0x8f870124, 0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001,
0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054,
0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400015, 0xa821,
@@ -3821,12 +3843,12 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xafb30010, 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809,
0x24c6001c, 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9,
0x1440ffee, 0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001,
-0x24842940, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
-0x34a5f011, 0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0,
+0x24842a70, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009,
+0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0,
0x8ec202d0, 0x8ec20220, 0x24420001, 0xaec20220, 0x8ec20220, 0x8ec20258,
0x24420001, 0xaec20258, 0x8ec20258, 0x8fbf0048, 0x8fbe0044, 0x8fb50040,
0x8fb3003c, 0x8fb10038, 0x3e00008, 0x27bd0050, 0x0, 0x0,
-0x27bdffe8, 0x27644000, 0xafbf0010, 0xc00296c, 0x24051000, 0x24020020,
+0x27bdffe8, 0x27644000, 0xafbf0010, 0xc002990, 0x24051000, 0x24020020,
0xaf82011c, 0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114,
0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134,
0xaf800138, 0xaec000dc, 0xaec000e0, 0xaec000e4, 0xaec000e8, 0x3c020001,
@@ -3835,173 +3857,179 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x3c026000, 0x1062000b, 0x0, 0x10000010, 0x0, 0x8f420218,
0x30420040, 0x14400009, 0x0, 0x8f820050, 0x3c030010, 0x10000003,
0x431024, 0x8f420218, 0x30420040, 0x10400004, 0x0, 0x8f82011c,
-0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8faa0010,
-0x8f83012c, 0x8fab0014, 0x1060000c, 0x8fac0018, 0x8ec20534, 0x8f890128,
-0x24680020, 0x51020005, 0x27624800, 0x11280005, 0x24620020, 0x10000009,
-0x0, 0x15220007, 0x24620020, 0x8ec30298, 0x1021, 0x24630001,
-0xaec30298, 0x1000006b, 0x8ec30298, 0xac640000, 0xac650004, 0xac660008,
-0xa467000e, 0xac6a0018, 0xac6b001c, 0xac6c0010, 0x2543ffee, 0x2c630002,
-0xaf820120, 0x39420011, 0x2c420001, 0x621825, 0x10600025, 0x0,
-0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x8c830000, 0x24020012,
-0x1462000f, 0x0, 0x8ec300e4, 0x8ec200e8, 0x1062000b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ec200e8, 0x8ec500e4, 0x24420001,
-0x1043002b, 0x0, 0x10000023, 0x0, 0x8ec200e4, 0x24030040,
-0x24420001, 0x50430003, 0x1021, 0x8ec200e4, 0x24420001, 0xaec200e4,
-0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x10000034, 0x24020012,
-0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x8c830000, 0x24020007,
-0x1462001f, 0x0, 0x8ec300e4, 0x8ec200e8, 0x1062001b, 0x24030040,
-0x8c820004, 0x24420001, 0xac820004, 0x8ec200e8, 0x8ec500e4, 0x24420001,
-0x10430007, 0x0, 0x8ec200e8, 0x24420001, 0x10a20005, 0x0,
-0x10000007, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020,
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000,
-0x10000012, 0x24020001, 0x8ec200e4, 0x24030040, 0x24420001, 0x50430003,
-0x1021, 0x8ec200e4, 0x24420001, 0xaec200e4, 0x8ec200e4, 0x210c0,
-0x24426fc0, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004,
-0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x8faa0010,
-0x8fab0014, 0x8f880120, 0x8ec20534, 0x8fac0018, 0x25030020, 0x14620002,
-0x604821, 0x27694800, 0x8f820128, 0x1122000c, 0x25030016, 0xad040000,
-0xad050004, 0xad060008, 0xa507000e, 0xad0a0018, 0xad0b001c, 0xad030014,
-0xad0c0010, 0xaf890120, 0x10000006, 0x24020001, 0x8ec30298, 0x1021,
-0x24630001, 0xaec30298, 0x8ec30298, 0x3e00008, 0x0, 0x3e00008,
-0x0, 0x8faa0010, 0x8f83010c, 0x8fab0014, 0x1060000c, 0x8fac0018,
-0x8f890108, 0x24680020, 0x27624800, 0x51020005, 0x27624000, 0x11280005,
-0x24620020, 0x10000009, 0x0, 0x15220007, 0x24620020, 0x8ec3029c,
-0x1021, 0x24630001, 0xaec3029c, 0x10000052, 0x8ec3029c, 0xac640000,
-0xac650004, 0xac660008, 0xa467000e, 0xac6a0018, 0xac6b001c, 0xac6c0010,
-0xaf820100, 0x2542fffb, 0x2c420002, 0x10400037, 0x24030040, 0x8ec200dc,
-0x210c0, 0x24426dc0, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f,
-0x0, 0x8ec300dc, 0x8ec200e0, 0x1062001b, 0x24030040, 0x8c820004,
-0x24420001, 0xac820004, 0x8ec200e0, 0x8ec500dc, 0x24420001, 0x10430007,
-0x0, 0x8ec200e0, 0x24420001, 0x10a20005, 0x0, 0x10000007,
-0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108,
-0x8f820108, 0x8c820004, 0x2c420011, 0x50400021, 0xac800000, 0x10000020,
-0x24020001, 0x8ec200dc, 0x24030040, 0x24420001, 0x50430003, 0x1021,
-0x8ec200dc, 0x24420001, 0xaec200dc, 0x8ec200dc, 0x210c0, 0x24426dc0,
-0x2e22021, 0x24020005, 0xac820000, 0x1000000e, 0x24020001, 0x8ec200dc,
-0x24420001, 0x50430003, 0x1021, 0x8ec200dc, 0x24420001, 0xaec200dc,
-0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x24020001, 0xac8a0000,
-0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0,
-0x8f880100, 0x8fa30010, 0x8faa0014, 0x8fab0018, 0x27624800, 0x25090020,
-0x122102b, 0x50400001, 0x27694000, 0x8f820108, 0x1122000d, 0x0,
-0xad030018, 0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e,
-0xad0a001c, 0xad030014, 0xad0b0010, 0xaf890100, 0x10000006, 0x24020001,
+0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8fa90010,
+0x8f83012c, 0x8faa0014, 0x8fab0018, 0x1060000a, 0x24680020, 0x8ec20534,
+0x51020001, 0x27684800, 0x8f820128, 0x11020004, 0x0, 0x8f820124,
+0x15020007, 0x39220011, 0x8ec30298, 0x1021, 0x24630001, 0xaec30298,
+0x10000069, 0x8ec30298, 0xac640000, 0xac650004, 0xac660008, 0xa467000e,
+0xac690018, 0xac6a001c, 0xac6b0010, 0x2523ffee, 0x2c630002, 0x2c420001,
+0x621825, 0x10600025, 0xaf880120, 0x8ec200e4, 0x210c0, 0x24426fc0,
+0x2e22021, 0x8c830000, 0x24020012, 0x1462000f, 0x0, 0x8ec300e4,
+0x8ec200e8, 0x1062000b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
+0x8ec200e8, 0x8ec500e4, 0x24420001, 0x1043002b, 0x0, 0x10000023,
+0x0, 0x8ec200e4, 0x24030040, 0x24420001, 0x50430003, 0x1021,
+0x8ec200e4, 0x24420001, 0xaec200e4, 0x8ec200e4, 0x210c0, 0x24426fc0,
+0x2e22021, 0x10000034, 0x24020012, 0x8ec200e4, 0x210c0, 0x24426fc0,
+0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ec300e4,
+0x8ec200e8, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004,
+0x8ec200e8, 0x8ec500e4, 0x24420001, 0x10430007, 0x0, 0x8ec200e8,
+0x24420001, 0x10a20005, 0x0, 0x10000007, 0x0, 0x14a00005,
+0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004,
+0x2c420011, 0x50400013, 0xac800000, 0x10000012, 0x24020001, 0x8ec200e4,
+0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ec200e4, 0x24420001,
+0xaec200e4, 0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x24020007,
+0xac820000, 0x24020001, 0xac820004, 0x24020001, 0x3e00008, 0x0,
+0x3e00008, 0x0, 0x8faa0010, 0x8fab0014, 0x8f880120, 0x8ec20534,
+0x8fac0018, 0x25030020, 0x14620002, 0x604821, 0x27694800, 0x8f820128,
+0x1122000c, 0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e,
+0xad0a0018, 0xad0b001c, 0xad030014, 0xad0c0010, 0xaf890120, 0x10000006,
+0x24020001, 0x8ec30298, 0x1021, 0x24630001, 0xaec30298, 0x8ec30298,
+0x3e00008, 0x0, 0x3e00008, 0x0, 0x8fa90010, 0x8f83010c,
+0x8faa0014, 0x8fab0018, 0x1060000a, 0x24680020, 0x27624800, 0x51020001,
+0x27684000, 0x8f820108, 0x11020004, 0x0, 0x8f820104, 0x15020007,
+0x2522fffb, 0x8ec3029c, 0x1021, 0x24630001, 0xaec3029c, 0x10000051,
+0x8ec3029c, 0x2c420002, 0xac640000, 0xac650004, 0xac660008, 0xa467000e,
+0xac690018, 0xac6a001c, 0xac6b0010, 0xaf880100, 0x10400037, 0x24030040,
+0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x8c830000, 0x24020005,
+0x1462001f, 0x0, 0x8ec300dc, 0x8ec200e0, 0x1062001b, 0x24030040,
+0x8c820004, 0x24420001, 0xac820004, 0x8ec200e0, 0x8ec500dc, 0x24420001,
+0x10430007, 0x0, 0x8ec200e0, 0x24420001, 0x10a20005, 0x0,
+0x10000007, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020,
+0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400021, 0xac800000,
+0x10000020, 0x24020001, 0x8ec200dc, 0x24030040, 0x24420001, 0x50430003,
+0x1021, 0x8ec200dc, 0x24420001, 0xaec200dc, 0x8ec200dc, 0x210c0,
+0x24426dc0, 0x2e22021, 0x24020005, 0xac820000, 0x1000000e, 0x24020001,
+0x8ec200dc, 0x24420001, 0x50430003, 0x1021, 0x8ec200dc, 0x24420001,
+0xaec200dc, 0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x24020001,
+0xac890000, 0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008,
+0x0, 0x8fab0010, 0x8f880100, 0x8faa0014, 0x8fac0018, 0x27624800,
+0x25030020, 0x14620002, 0x604821, 0x27694000, 0x8f820108, 0x1122000c,
+0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, 0xad0b0018,
+0xad0a001c, 0xad030014, 0xad0c0010, 0xaf890100, 0x10000006, 0x24020001,
0x8ec3029c, 0x1021, 0x24630001, 0xaec3029c, 0x8ec3029c, 0x3e00008,
0x0, 0x3e00008, 0x0, 0x27bdffe0, 0xafbf0018, 0x8f820104,
-0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c,
-0x3c040001, 0x24842a2c, 0xc0028eb, 0x34a5f000, 0x8f420218, 0x30420100,
+0xafa20010, 0x8f820100, 0x3c040001, 0x24842b5c, 0xafa20014, 0x8f8600b0,
+0x8f87011c, 0x3c050002, 0xc00290f, 0x34a5f000, 0x8f420218, 0x30420100,
0x10400017, 0x0, 0x8f8200b0, 0x3c030200, 0x431024, 0x10400012,
0x0, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0,
0x34420001, 0xaf8200b0, 0xaf830104, 0x8f82011c, 0x2403fffd, 0x431024,
-0xaf82011c, 0x8ec20294, 0x24420001, 0xaec20294, 0x10000004, 0x8ec20294,
-0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, 0x3e00008, 0x27bd0020,
-0x27bdffe0, 0xafbf0018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001,
-0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001, 0x24842a38, 0xc0028eb,
-0x34a5f000, 0x8f420218, 0x30420100, 0x10400017, 0x0, 0x8f8200a0,
-0x3c030200, 0x431024, 0x10400012, 0x0, 0x8f82011c, 0x34420002,
-0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0xaf830124,
-0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ec20290, 0x24420001,
-0xaec20290, 0x10000004, 0x8ec20290, 0x8f8200a0, 0x34420001, 0xaf8200a0,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x6021, 0x5021, 0x3021,
-0x2821, 0x6821, 0x4821, 0x7821, 0x7021, 0x8f880124,
-0x8f870104, 0x1580002e, 0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120,
-0x10460029, 0x0, 0x3c040001, 0x8c843390, 0x8cc20000, 0x8cc30004,
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
-0x10400017, 0x0, 0x3c040001, 0x8c843390, 0x8d020000, 0x8d030004,
-0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021,
-0x1540002f, 0x31620100, 0x11200014, 0x31628000, 0x8f820100, 0x1045002a,
-0x31620100, 0x3c040001, 0x8c84338c, 0x8ca20000, 0x8ca30004, 0xac820000,
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
-0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
-0x31620100, 0x3c040001, 0x8c84338c, 0x8ce20000, 0x8ce30004, 0xac820000,
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
-0x24e50020, 0xac820010, 0x8ce20014, 0x240a0001, 0xa01821, 0xac820014,
-0x276247e0, 0x43102b, 0x54400001, 0x27634000, 0x602821, 0x31620100,
-0x5440001d, 0x31621000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821,
-0x11800011, 0x31621000, 0x3c040001, 0x8c843390, 0x8c820000, 0x8c830004,
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000,
-0x1440ff82, 0x0, 0x1120000f, 0x31220800, 0x10400004, 0x3c020002,
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1221024, 0x10400004, 0x24e20020,
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x4821,
-0x1140ff70, 0x0, 0x3c040001, 0x8c84338c, 0x8c820000, 0x8c830004,
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
-0x8c820010, 0x5021, 0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014,
-0x3e00008, 0x0, 0x6021, 0x5821, 0x3021, 0x2821,
-0x6821, 0x5021, 0x7821, 0x7021, 0x8f880124, 0x8f870104,
-0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120,
-0x10460029, 0x0, 0x3c040001, 0x8c843390, 0x8cc20000, 0x8cc30004,
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e,
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020,
-0x10400017, 0x0, 0x3c040001, 0x8c843390, 0x8d020000, 0x8d030004,
-0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e,
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821,
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021,
-0x1560002f, 0x31220100, 0x11400014, 0x31228000, 0x8f820100, 0x1045002a,
-0x31220100, 0x3c040001, 0x8c84338c, 0x8ca20000, 0x8ca30004, 0xac820000,
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010,
-0x240b0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018,
-0x31220100, 0x3c040001, 0x8c84338c, 0x8ce20000, 0x8ce30004, 0xac820000,
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010,
-0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, 0xa01821, 0xac820014,
-0x276247e0, 0x43102b, 0x54400001, 0x27634000, 0x602821, 0x31220100,
-0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020,
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821,
-0x11800011, 0x31221000, 0x3c040001, 0x8c843390, 0x8c820000, 0x8c830004,
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac,
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31221000,
-0x14400022, 0x0, 0x1140000f, 0x31420800, 0x10400004, 0x3c020002,
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 0x10400004, 0x24e20020,
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x5021,
-0x11600010, 0x0, 0x3c040001, 0x8c84338c, 0x8c820000, 0x8c830004,
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c,
-0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, 0x8c8e0014, 0x8f820070,
-0x3c031000, 0x431024, 0x1040ff5c, 0x0, 0x8f820054, 0x24420005,
-0xaf820078, 0x8f420234, 0x10400017, 0x2021, 0x3c020001, 0x571021,
-0x8c4281dc, 0x24420005, 0x3c010001, 0x370821, 0xac2281dc, 0x3c020001,
-0x571021, 0x8c4281dc, 0x8f430234, 0x43102b, 0x14400009, 0x24020001,
-0x3c040080, 0x3c010001, 0x370821, 0xac2281d4, 0x3c010001, 0x370821,
-0x1000000c, 0xac2081dc, 0x3c020001, 0x571021, 0x8c4281d4, 0x14400006,
-0x3c020080, 0x3c020001, 0x571021, 0x8c4281d8, 0x10400002, 0x3c020080,
-0x822025, 0x8f420230, 0x10400014, 0x0, 0x3c020001, 0x571021,
-0x8c4281e4, 0x24420005, 0x3c010001, 0x370821, 0xac2281e4, 0x3c020001,
-0x571021, 0x8c4281e4, 0x8f430230, 0x43102b, 0x14400006, 0x0,
-0x3c010001, 0x370821, 0xac2081e4, 0x10000006, 0x982025, 0x3c020001,
-0x571021, 0x8c4281e0, 0x54400001, 0x982025, 0x3c020001, 0x571021,
-0x8c4281e8, 0x10400005, 0x3c022000, 0x822025, 0x3c010001, 0x370821,
-0xac2081e8, 0x1080ff0f, 0x0, 0x8ec20000, 0x10400007, 0x0,
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0,
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x441025,
-0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x1000fefa, 0xaf80004c,
-0x1000fef8, 0xaf800048, 0x3e00008, 0x0, 0x3c020001, 0x8c423228,
-0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb10010, 0x3c110001, 0x26313430,
-0x2202021, 0xc00296c, 0x24052000, 0x26221fe0, 0x3c010001, 0xac223398,
-0x3c010001, 0xac223394, 0xaf420250, 0x24022000, 0xaf510254, 0xaf420258,
-0x24020001, 0x3c010001, 0xac223228, 0x8fbf0014, 0x8fb10010, 0x3e00008,
-0x27bd0018, 0x3c030001, 0x8c633398, 0x8c820000, 0x8fa80010, 0x8fa90014,
-0xac620000, 0x3c020001, 0x8c423398, 0x8c830004, 0xac430004, 0xac450008,
+0xaf82011c, 0x8ec20294, 0x24420001, 0xaec20294, 0x10000018, 0x8ec20294,
+0x3c040001, 0x24842b68, 0x3405dead, 0x3021, 0x3c070001, 0x24e72b70,
+0x24020287, 0xafa20010, 0xc00290f, 0xafa00014, 0x8f82011c, 0x34420002,
+0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001,
+0x431025, 0xaf820140, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018,
+0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8f820120, 0xafa20010,
+0x8f820124, 0x3c040001, 0x24842b98, 0xafa20014, 0x8f8600a0, 0x8f87011c,
+0x3c050001, 0xc00290f, 0x34a5f000, 0x8f420218, 0x30420100, 0x10400017,
+0x0, 0x8f8200a0, 0x3c030200, 0x431024, 0x10400012, 0x0,
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001,
+0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c,
+0x8ec20290, 0x24420001, 0xaec20290, 0x10000018, 0x8ec20290, 0x3c040001,
+0x24842b68, 0x3405dead, 0x3021, 0x3c070001, 0x24e72b70, 0x240202a3,
+0xafa20010, 0xc00290f, 0xafa00014, 0x8f82011c, 0x34420002, 0xaf82011c,
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025,
+0xaf820140, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x6021, 0x5021, 0x3021, 0x2821, 0x6821,
+0x4821, 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x1580002e,
+0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, 0x10460029, 0x0,
+0x3c040001, 0x8c8434f0, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0,
+0x3c040001, 0x8c8434f0, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0,
+0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1540002f, 0x31620100,
+0x11200014, 0x31628000, 0x8f820100, 0x1045002a, 0x31620100, 0x3c040001,
+0x8c8434ec, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240a0001, 0xac820010,
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31620100, 0x3c040001,
+0x8c8434ec, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
+0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, 0x276247e0, 0x43102b,
+0x54400001, 0x27634000, 0x602821, 0x31620100, 0x5440001d, 0x31621000,
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
+0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31621000,
+0x3c040001, 0x8c8434f0, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, 0x1440ff82, 0x0,
+0x1120000f, 0x31220800, 0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000,
+0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
+0x24e20020, 0xaf820104, 0x8f870104, 0x4821, 0x1140ff70, 0x0,
+0x3c040001, 0x8c8434ec, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5021,
+0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, 0x3e00008, 0x0,
+0x6021, 0x5821, 0x3021, 0x2821, 0x6821, 0x5021,
+0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x3c180100, 0x1580002e,
+0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, 0x10460029, 0x0,
+0x3c040001, 0x8c8434f0, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004,
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001,
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0,
+0x3c040001, 0x8c8434f0, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004,
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020,
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0,
+0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1560002f, 0x31220100,
+0x11400014, 0x31228000, 0x8f820100, 0x1045002a, 0x31220100, 0x3c040001,
+0x8c8434ec, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008,
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010,
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31220100, 0x3c040001,
+0x8c8434ec, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008,
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010,
+0x8ce20014, 0x240b0001, 0xa01821, 0xac820014, 0x276247e0, 0x43102b,
+0x54400001, 0x27634000, 0x602821, 0x31220100, 0x5440001d, 0x31221000,
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000,
+0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31221000,
+0x3c040001, 0x8c8434f0, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084,
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021,
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31221000, 0x14400022, 0x0,
+0x1140000f, 0x31420800, 0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000,
+0x3c020002, 0x1421024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4,
+0x24e20020, 0xaf820104, 0x8f870104, 0x5021, 0x11600010, 0x0,
+0x3c040001, 0x8c8434ec, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094,
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5821,
+0xaf8200b0, 0x8c8a0010, 0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024,
+0x1040ff5c, 0x0, 0x8f820054, 0x24420005, 0xaf820078, 0x8f420234,
+0x10400017, 0x2021, 0x3c020001, 0x571021, 0x8c4281dc, 0x24420005,
+0x3c010001, 0x370821, 0xac2281dc, 0x3c020001, 0x571021, 0x8c4281dc,
+0x8f430234, 0x43102b, 0x14400009, 0x24020001, 0x3c040080, 0x3c010001,
+0x370821, 0xac2281d4, 0x3c010001, 0x370821, 0x1000000c, 0xac2081dc,
+0x3c020001, 0x571021, 0x8c4281d4, 0x14400006, 0x3c020080, 0x3c020001,
+0x571021, 0x8c4281d8, 0x10400002, 0x3c020080, 0x822025, 0x8f420230,
+0x10400014, 0x0, 0x3c020001, 0x571021, 0x8c4281e4, 0x24420005,
+0x3c010001, 0x370821, 0xac2281e4, 0x3c020001, 0x571021, 0x8c4281e4,
+0x8f430230, 0x43102b, 0x14400006, 0x0, 0x3c010001, 0x370821,
+0xac2081e4, 0x10000006, 0x982025, 0x3c020001, 0x571021, 0x8c4281e0,
+0x54400001, 0x982025, 0x3c020001, 0x571021, 0x8c4281e8, 0x10400005,
+0x3c022000, 0x822025, 0x3c010001, 0x370821, 0xac2081e8, 0x1080ff0f,
+0x0, 0x8ec20000, 0x10400007, 0x0, 0xaf80004c, 0x8f82004c,
+0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048,
+0x1040fffd, 0x0, 0x8f820060, 0x441025, 0xaf820060, 0x8ec20000,
+0x10400003, 0x0, 0x1000fefa, 0xaf80004c, 0x1000fef8, 0xaf800048,
+0x3e00008, 0x0, 0x0, 0x0, 0x3c020001, 0x8c423388,
+0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb10010, 0x3c110001, 0x26313590,
+0x2202021, 0xc002990, 0x24052000, 0x26221fe0, 0x3c010001, 0xac2234f8,
+0x3c010001, 0xac2234f4, 0xaf420250, 0x24022000, 0xaf510254, 0xaf420258,
+0x24020001, 0x3c010001, 0xac223388, 0x8fbf0014, 0x8fb10010, 0x3e00008,
+0x27bd0018, 0x3c030001, 0x8c6334f8, 0x8c820000, 0x8fa80010, 0x8fa90014,
+0xac620000, 0x3c020001, 0x8c4234f8, 0x8c830004, 0xac430004, 0xac450008,
0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, 0xac480018, 0xac49001c,
-0x3c010001, 0xac233398, 0xac44000c, 0x3c020001, 0x24423430, 0x62182b,
-0x10600005, 0x0, 0x3c020001, 0x8c423394, 0x3c010001, 0xac223398,
-0x3c030001, 0x8c633398, 0x3c020001, 0x8c423210, 0xac620000, 0x3c030001,
-0x8c633398, 0x3c020001, 0x8c423210, 0xac620004, 0x3e00008, 0xaf430250,
-0x27bdffd8, 0xafb10010, 0x808821, 0x3c030001, 0x8c633398, 0x3c020001,
-0x8c423210, 0x8fa40040, 0xafb30014, 0xa09821, 0xafbf0020, 0xafbe001c,
-0xafb50018, 0xac620000, 0x3c050001, 0x8ca53398, 0x3c020001, 0x8c423210,
-0xc0a821, 0xe0f021, 0x10800006, 0xaca20004, 0x24a50008, 0xc002974,
-0x24060018, 0x10000004, 0x0, 0x24a40008, 0xc00296c, 0x24050018,
-0x3c020001, 0x8c423398, 0x3c050001, 0x24a53430, 0x2442ffe0, 0x3c010001,
-0xac223398, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c423394,
-0x3c010001, 0xac223398, 0x3c030001, 0x8c633398, 0x8e220000, 0xac620000,
-0x3c030001, 0x8c633398, 0x8e220004, 0xac620004, 0xac730008, 0x8f840054,
+0x3c010001, 0xac2334f8, 0xac44000c, 0x3c020001, 0x24423590, 0x62182b,
+0x10600005, 0x0, 0x3c020001, 0x8c4234f4, 0x3c010001, 0xac2234f8,
+0x3c030001, 0x8c6334f8, 0x3c020001, 0x8c423370, 0xac620000, 0x3c030001,
+0x8c6334f8, 0x3c020001, 0x8c423370, 0xac620004, 0x3e00008, 0xaf430250,
+0x27bdffd8, 0xafb10010, 0x808821, 0x3c030001, 0x8c6334f8, 0x3c020001,
+0x8c423370, 0x8fa40040, 0xafb30014, 0xa09821, 0xafbf0020, 0xafbe001c,
+0xafb50018, 0xac620000, 0x3c050001, 0x8ca534f8, 0x3c020001, 0x8c423370,
+0xc0a821, 0xe0f021, 0x10800006, 0xaca20004, 0x24a50008, 0xc002998,
+0x24060018, 0x10000004, 0x0, 0x24a40008, 0xc002990, 0x24050018,
+0x3c020001, 0x8c4234f8, 0x3c050001, 0x24a53590, 0x2442ffe0, 0x3c010001,
+0xac2234f8, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c4234f4,
+0x3c010001, 0xac2234f8, 0x3c030001, 0x8c6334f8, 0x8e220000, 0xac620000,
+0x3c030001, 0x8c6334f8, 0x8e220004, 0xac620004, 0xac730008, 0x8f840054,
0xac750010, 0xac7e0014, 0x8fa80038, 0xac680018, 0x8fa8003c, 0x2462ffe0,
-0x3c010001, 0xac223398, 0x45102b, 0xac68001c, 0x10400005, 0xac64000c,
-0x3c020001, 0x8c423394, 0x3c010001, 0xac223398, 0x3c030001, 0x8c633398,
-0x3c020001, 0x8c423210, 0xac620000, 0x3c030001, 0x8c633398, 0x3c020001,
-0x8c423210, 0xac620004, 0xaf430250, 0x8fbf0020, 0x8fbe001c, 0x8fb50018,
+0x3c010001, 0xac2234f8, 0x45102b, 0xac68001c, 0x10400005, 0xac64000c,
+0x3c020001, 0x8c4234f4, 0x3c010001, 0xac2234f8, 0x3c030001, 0x8c6334f8,
+0x3c020001, 0x8c423370, 0xac620000, 0x3c030001, 0x8c6334f8, 0x3c020001,
+0x8c423370, 0xac620004, 0xaf430250, 0x8fbf0020, 0x8fbe001c, 0x8fb50018,
0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x10a00005, 0x0,
0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 0x3e00008, 0x0,
0x10c00007, 0x0, 0x8c820000, 0x24840004, 0x24c6fffc, 0xaca20000,
@@ -4025,7 +4053,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x24020017, 0x24020006, 0xafa20010, 0x8ec2001c, 0xafa20014, 0x8ec2000c,
0x8fa40028, 0x8fa5002c, 0x3c030002, 0x431025, 0xafa20018, 0x8ec60080,
0x8ec200a4, 0x40f809, 0x0, 0x5440000b, 0x3225ffff, 0x8fa9002c,
-0xafa90010, 0x8ec20080, 0x3c040001, 0x24842cfc, 0x3c050004, 0xafa20014,
+0xafa90010, 0x8ec20080, 0x3c040001, 0x24842e5c, 0x3c050004, 0xafa20014,
0x8ec6001c, 0x100000a5, 0x34a5f004, 0x8ec20078, 0x451021, 0xaec20078,
0x8ec2001c, 0x8ee304bc, 0x8ec40074, 0x21100, 0x431021, 0xac44000c,
0x8ec30074, 0xafa30020, 0x8ec40078, 0xafa40024, 0x8ec2052c, 0x10400006,
@@ -4037,8 +4065,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x8ec202a8, 0x1821, 0x24420001, 0xaec202a8, 0x10000008,
0x8ec202a8, 0x8fa20020, 0x8fa30024, 0xacc20000, 0xacc30004, 0x24c20008,
0xaf8200f0, 0x24030001, 0x14600012, 0x131142, 0x8f8200f0, 0xafa20010,
-0x8f8200f4, 0x3c040001, 0x24842d08, 0xafa20014, 0x8fa60020, 0x8fa70024,
-0x3c050004, 0xc0028eb, 0x34a5f005, 0x8ec20180, 0x24420001, 0xaec20180,
+0x8f8200f4, 0x3c040001, 0x24842e68, 0xafa20014, 0x8fa60020, 0x8fa70024,
+0x3c050004, 0xc00290f, 0x34a5f005, 0x8ec20180, 0x24420001, 0xaec20180,
0x8ec20180, 0x10000039, 0x24020001, 0x30430003, 0x24020002, 0x10620016,
0x28620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x10000023,
0x0, 0x24020003, 0x10620017, 0x0, 0x1000001e, 0x0,
@@ -4052,8 +4080,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x1000002f, 0xa2c20529, 0x3227ffff, 0x10e0002c, 0x0, 0x14400002,
0x24020016, 0x24020005, 0xafa20010, 0x8ec2001c, 0x8fa40028, 0x8fa5002c,
0xafa20014, 0x8ec2000c, 0xafa20018, 0x8ec60080, 0x8ec200a4, 0x40f809,
-0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842d14, 0x8fa8002c,
-0x3c050004, 0xafa00014, 0xafa80010, 0x8ec6001c, 0x34a5f007, 0xc0028eb,
+0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842e74, 0x8fa8002c,
+0x3c050004, 0xafa00014, 0xafa80010, 0x8ec6001c, 0x34a5f007, 0xc00290f,
0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, 0x451021,
0xaec20080, 0x8ec20078, 0x8ec30080, 0x451021, 0x64182b, 0x14600005,
0xaec20078, 0x8ec20080, 0x8ec3053c, 0x431023, 0xaec20080, 0xa2c00529,
@@ -4086,7 +4114,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xafa20010, 0x8ec2001c, 0x8fa40020, 0x8fa50024, 0x3c030002, 0xc31825,
0xafa30018, 0xafa20014, 0x8ec60080, 0x8ec200a4, 0x40f809, 0x0,
0x1440000b, 0x24030001, 0x8fab0024, 0xafab0010, 0x8ec20080, 0x3c040001,
-0x24842cfc, 0x3c050004, 0xafa20014, 0x8ec60018, 0x10000037, 0x34a5f004,
+0x24842e5c, 0x3c050004, 0xafa20014, 0x8ec60018, 0x10000037, 0x34a5f004,
0x8ec40070, 0x8ec20080, 0x8ec50538, 0x2406fff8, 0xa2c30021, 0xaec0052c,
0xaec00530, 0x24840001, 0xaec40070, 0x3224ffff, 0x441021, 0x24420007,
0x461024, 0x24840007, 0xaec20074, 0x8ec20088, 0x8ec30074, 0x862024,
@@ -4094,9 +4122,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x431023, 0xaec20074, 0x8ec20074, 0x1000002d, 0xaec20080, 0x10e0002b,
0x0, 0x15000002, 0x24020016, 0x24020005, 0xafa20010, 0x8ec2001c,
0x8fa40020, 0x8fa50024, 0xafa60018, 0xafa20014, 0x8ec60080, 0x8ec200a4,
-0x40f809, 0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842d14,
+0x40f809, 0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842e74,
0x8faa0024, 0x3c050004, 0xafa00014, 0xafaa0010, 0x8ec60018, 0x34a5f007,
-0xc0028eb, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538,
+0xc00290f, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538,
0x451021, 0xaec20080, 0x8ec20088, 0x8ec30080, 0xa2c00021, 0x451023,
0x64182b, 0x14600005, 0xaec20088, 0x8ec20080, 0x8ec3053c, 0x431023,
0xaec20080, 0x8ec3001c, 0x96e20450, 0x24630001, 0x2442ffff, 0x621824,
@@ -4119,26 +4147,26 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x0, 0x96e20452, 0x8ed10018, 0x30420020, 0x1040001e, 0x24070008,
0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010,
0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b,
-0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c,
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x1040004a,
+0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040004a,
0x24020001, 0x3c010001, 0x370821, 0x1000006f, 0xac2281d0, 0x8ee40498,
0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014,
0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001,
-0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228,
-0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x1040004f, 0x24020001,
+0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228,
+0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040004f, 0x24020001,
0x10000051, 0x0, 0x2c420002, 0x10400062, 0x24a2fffe, 0x8cc2001c,
0x96e30450, 0x8ec40024, 0x24420001, 0x2463ffff, 0x431024, 0x872021,
0xaec20018, 0xaec40024, 0x96e20452, 0x8ed10018, 0x30420020, 0x10400023,
0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019,
0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c,
-0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014,
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021,
+0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014,
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021,
0x14400006, 0x24020001, 0x24020001, 0x3c010001, 0x370821, 0x10000031,
0xac2281d8, 0x3c010001, 0x370821, 0x10000021, 0xac2281d0, 0x8ee40498,
0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014,
0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001,
-0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228,
-0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001,
+0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228,
+0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001,
0x3c010001, 0x370821, 0x10000010, 0xac2281d4, 0x3c010001, 0x370821,
0xac2081d0, 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821,
0xac2081d4, 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264,
@@ -4150,12 +4178,12 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ec202c4, 0x641821, 0x306300ff, 0x10000009, 0xaec3005c, 0x8ec202bc,
0x8ec3003c, 0x441021, 0xaec202bc, 0x8ec202c4, 0x641821, 0x306301ff,
0xaec3003c, 0x441021, 0xaec202c4, 0x10000022, 0x36940040, 0x24020014,
-0x14a20014, 0x24020010, 0x3c020001, 0x8c4231d4, 0x1040000a, 0x26e50028,
+0x14a20014, 0x24020010, 0x3c020001, 0x8c423334, 0x1040000a, 0x26e50028,
0x26c40128, 0x240300ff, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff,
0xac820000, 0x1466fffb, 0x24840004, 0x8ec20240, 0xa2c00528, 0x24420001,
0xaec20240, 0x1000000c, 0x8ec20240, 0x10a2000a, 0x3c050008, 0x94c7000e,
-0x8cc2001c, 0x3c040001, 0x24842d20, 0xafa60014, 0xafa20010, 0x8cc60018,
-0xc0028eb, 0x34a50910, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028,
+0x8cc2001c, 0x3c040001, 0x24842e80, 0xafa60014, 0xafa20010, 0x8cc60018,
+0xc00290f, 0x34a50910, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028,
0x3e00008, 0x0, 0x27bdff80, 0xafbf0078, 0xafbe0074, 0xafb50070,
0xafb3006c, 0xafb10068, 0x8f820104, 0x8f950108, 0xafa00034, 0x12a2039b,
0xafa0003c, 0x8f820108, 0x24420020, 0xaf820108, 0x8ead0018, 0xafad0044,
@@ -4185,8 +4213,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xaecd0094, 0x8ec3009c, 0x8ec20538, 0x24650017, 0xa2102b, 0x14400003,
0x0, 0x8ec2053c, 0xa22823, 0x90a50000, 0xa3a5005f, 0x93a6005f,
0x38c30006, 0x3182b, 0x38c20011, 0x2102b, 0x621824, 0x1060000c,
-0x3c050008, 0x8fad0054, 0xafad0010, 0x8ec2009c, 0x3c040001, 0x24842d2c,
-0xafa20014, 0x8ec70094, 0xc0028eb, 0x34a5f055, 0x100000d7, 0x0,
+0x3c050008, 0x8fad0054, 0xafad0010, 0x8ec2009c, 0x3c040001, 0x24842e8c,
+0xafa20014, 0x8ec70094, 0xc00290f, 0x34a5f055, 0x100000d7, 0x0,
0x96e20452, 0x30420008, 0x1040000c, 0x2625000e, 0x8ec20538, 0xa2102b,
0x14400003, 0xf021, 0x8ec2053c, 0xa22823, 0x90a20000, 0x3042000f,
0x21080, 0x10000068, 0xafa20028, 0x8ec20094, 0x8fad0054, 0x11a20013,
@@ -4264,13 +4292,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x2c420002, 0x1040012f, 0x0, 0x96e20452, 0x8ed10018, 0x30420020,
0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120,
0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809,
-0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010,
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006,
+0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010,
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006,
0x1021, 0x1040008f, 0x24020001, 0x3c010001, 0x370821, 0x100000b4,
0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012,
0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c,
-0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014,
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021,
+0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014,
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021,
0x10400094, 0x24020001, 0x10000096, 0x0, 0x15a20043, 0x24020016,
0x96a3000e, 0x8ec20078, 0x8ec40024, 0x431021, 0xaec20078, 0x8ea3001c,
0x96e20450, 0x24840001, 0xaec40024, 0x24630001, 0x2442ffff, 0x621824,
@@ -4278,8 +4306,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ed10018, 0x30420020, 0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c,
0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018,
0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001,
-0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
-0xc0028eb, 0x34a5f006, 0x1021, 0x1040003f, 0x24020001, 0x3c010001,
+0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
+0xc00290f, 0x34a5f006, 0x1021, 0x1040003f, 0x24020001, 0x3c010001,
0x370821, 0x10000064, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008,
0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8,
0x40f809, 0x24c6001c, 0x1040ffb1, 0x0, 0x1000ffb9, 0x24020001,
@@ -4288,14 +4316,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xaec30018, 0x96e20452, 0x8ed10018, 0x30420020, 0x10400023, 0x24070008,
0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010,
0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b,
-0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c,
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400006,
+0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400006,
0x24020001, 0x24020001, 0x3c010001, 0x370821, 0x10000031, 0xac2281d8,
0x3c010001, 0x370821, 0x10000021, 0xac2281d0, 0x8ee40498, 0x8ee5049c,
0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018,
0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001,
-0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
-0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001,
+0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009,
+0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001,
0x370821, 0x10000010, 0xac2281d4, 0x3c010001, 0x370821, 0xac2081d0,
0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4,
0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 0x8ec20264,
@@ -4307,11 +4335,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ec202c4, 0x641821, 0x306300ff, 0x10000009, 0xaec3005c, 0x8ec202bc,
0x8ec3003c, 0x441021, 0xaec202bc, 0x8ec202c4, 0x641821, 0x306301ff,
0xaec3003c, 0x441021, 0xaec202c4, 0x1000001f, 0x36940040, 0x8fad0044,
-0x24020014, 0x15a20010, 0x24020010, 0x3c020001, 0x8c4231d4, 0x10400017,
+0x24020014, 0x15a20010, 0x24020010, 0x3c020001, 0x8c423334, 0x10400017,
0x26e50028, 0x26c40128, 0x240300ff, 0x2406ffff, 0x8ca20000, 0x24a50004,
0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x1000000c, 0x0,
-0x11a2000a, 0x3c050008, 0x96a7000e, 0x8ea2001c, 0x3c040001, 0x24842d20,
-0xafb50014, 0xafa20010, 0x8ea60018, 0xc0028eb, 0x34a50910, 0x8fbf0078,
+0x11a2000a, 0x3c050008, 0x96a7000e, 0x8ea2001c, 0x3c040001, 0x24842e80,
+0xafb50014, 0xafa20010, 0x8ea60018, 0xc00290f, 0x34a50910, 0x8fbf0078,
0x8fbe0074, 0x8fb50070, 0x8fb3006c, 0x8fb10068, 0x3e00008, 0x27bd0080,
0x3e00008, 0x0, 0x803821, 0x8f8600e4, 0x8f8400e0, 0x2402fff8,
0x8cc30004, 0x822024, 0x10c4000d, 0x3c020100, 0x3c050100, 0x651024,
@@ -4338,14 +4366,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0xaf8800c8, 0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0, 0x27bdff70,
0xafbf0088, 0xafbe0084, 0xafb50080, 0xafb3007c, 0xafb10078, 0x92c200ed,
0xa3a0004f, 0x1040000b, 0xa3a00067, 0x8ecd00f0, 0xafad0034, 0x8ece00f4,
-0xafae002c, 0x8ecd00fc, 0x8ed500f8, 0xafad006c, 0x8ece0100, 0x100000d9,
-0xafae003c, 0x3c020001, 0x8c4233b8, 0x40f809, 0x27a40020, 0x1040026e,
+0xafae002c, 0x8ecd00fc, 0x8ed500f8, 0xafad006c, 0x8ece0100, 0x100000e9,
+0xafae003c, 0x3c020001, 0x8c423518, 0x40f809, 0x27a40020, 0x10400295,
0x0, 0x8fa30024, 0x8fb50020, 0x306dffff, 0x25adfffc, 0xafad0034,
0x92a20000, 0xafb5002c, 0x30420001, 0x10400017, 0xafa3006c, 0x8ec2011c,
0x3c03ffff, 0x431024, 0x14400012, 0x2402ffff, 0x8ea30000, 0x14620004,
0x3402ffff, 0x96a30004, 0x1062000c, 0x0, 0xc0022ad, 0x2a02021,
-0x304200ff, 0x14400007, 0x0, 0x3c020001, 0x8c4233b0, 0x40f809,
-0x0, 0x1000024e, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
+0x304200ff, 0x14400007, 0x0, 0x3c020001, 0x8c423510, 0x40f809,
+0x0, 0x10000275, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
0x431024, 0x3c03ffff, 0x432824, 0x14a00003, 0xafa20024, 0x10000053,
0x1821, 0x3c020080, 0xa21024, 0x50400007, 0x3c040040, 0x8ec202e4,
0x24420001, 0xaec202e4, 0x8ec202e4, 0x10000049, 0x24030001, 0x3c070004,
@@ -4362,1001 +4390,1008 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
0x8ec20128, 0x10000006, 0x42042, 0x8ec202e0, 0x24420001, 0xaec202e0,
0x8ec202e0, 0x42042, 0x1488ffc6, 0x851824, 0x24030001, 0x8f420260,
0x8fae0034, 0x4e102b, 0x10400015, 0x306400ff, 0x8f8200e0, 0xafa20010,
-0x8f8200e4, 0x3c040001, 0x24842dfc, 0xafa20014, 0x8fa60020, 0x8fa70024,
-0x3c050006, 0xc0028eb, 0x34a5f003, 0x8ec30150, 0x8fad006c, 0x3c020100,
+0x8f8200e4, 0x3c040001, 0x24842f5c, 0xafa20014, 0x8fa60020, 0x8fa70024,
+0x3c050006, 0xc00290f, 0x34a5f003, 0x8ec30150, 0x8fad006c, 0x3c020100,
0x24040001, 0x1a26825, 0x24630001, 0xafad006c, 0xaec30150, 0x8ec20150,
0x1080000f, 0x0, 0x8f420218, 0x30420800, 0x1440000b, 0x3c020180,
0x8fae006c, 0x1c21024, 0x10400005, 0x0, 0x8ec20174, 0x24420001,
-0xaec20174, 0x8ec20174, 0x100001bd, 0x8fa30034, 0x8f420218, 0x30420400,
+0xaec20174, 0x8ec20174, 0x100001e4, 0x8fa30034, 0x8f420218, 0x30420400,
0x10400004, 0x0, 0x8fad0034, 0x25ad0004, 0xafad0034, 0x8ec20050,
-0x5040001d, 0xafa0003c, 0x8fae0034, 0x4e102b, 0x50400019, 0xafa0003c,
-0x8ec20050, 0x1c21023, 0xafa2003c, 0x8ecd0050, 0x10000013, 0xafad0034,
-0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842e08, 0xafa20014,
-0x8ec6003c, 0x8ec70044, 0x3c050006, 0xc0028eb, 0x34a5f002, 0x8ec202b4,
-0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x10000172, 0x8ec202b4,
-0x96e20460, 0x8fae0034, 0x4e102b, 0x10400004, 0x0, 0x240d0001,
-0xa3ad004f, 0x8fae0034, 0x11c00189, 0x3c02ffff, 0x8fad006c, 0x1a21024,
-0xafa20074, 0x8ec20068, 0x8f430280, 0x24420001, 0x304203ff, 0x1062015f,
-0x0, 0x93a2004f, 0x10400015, 0x0, 0x8ec3005c, 0x8ec20060,
-0x1062000a, 0x26ce0060, 0x8ec60060, 0xafae0054, 0x8ec30060, 0x21140,
-0x24424dc0, 0x2e28821, 0x24630001, 0x10000014, 0x306300ff, 0x92c20064,
-0x1440ffc9, 0x0, 0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8,
-0x8ec3003c, 0x8ec20044, 0x1062ffc1, 0x26cd0044, 0x8ec60044, 0xafad0054,
-0x8ec30044, 0x21140, 0x24420dc0, 0x2e28821, 0x24630001, 0x306301ff,
-0xafa3005c, 0x96e20462, 0x30420010, 0x1040001a, 0x340e8100, 0x96a2000c,
-0x144e0017, 0x0, 0x92c200ed, 0x14400014, 0x0, 0x96a2000e,
-0xa6220016, 0x8ea20008, 0x8ea30004, 0x8fad0034, 0x8ea40000, 0x25adfffc,
-0xafad0034, 0xaea2000c, 0xaea30008, 0xaea40004, 0x9622000e, 0x8fae002c,
-0x240d0001, 0xa3ad0067, 0x25ce0004, 0x34420200, 0xafae002c, 0xa622000e,
-0x9627000a, 0x8fae0034, 0xee102b, 0x14400002, 0x30f3fff8, 0x8fb30034,
-0x8e240000, 0x8e250004, 0x8fad002c, 0x24020007, 0xae2d0018, 0xafa20010,
-0xafa60014, 0x8ec20004, 0x8fa6002c, 0xafa20018, 0x8ec200a8, 0x40f809,
-0x2603821, 0x1440001a, 0x3c050006, 0x3c040001, 0x24842e14, 0x8e220018,
-0x34a5f009, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x2603821,
-0xc0028eb, 0xafa30014, 0x93a20067, 0x104000fb, 0x0, 0x8ea20004,
-0x8ea30008, 0x8ea4000c, 0x340e8100, 0xa6ae000c, 0xaea20000, 0xaea30004,
-0xaea40008, 0x96220016, 0x100000f0, 0xa6a2000e, 0x8fad0034, 0x166d0089,
-0x0, 0x962e000a, 0xafae0044, 0x8fae003c, 0x9623000e, 0x1ae1021,
-0xa622000a, 0x34620004, 0xa622000e, 0x8fad0074, 0x11a00006, 0x307effff,
-0x34620404, 0xa622000e, 0x8fae006c, 0xe1402, 0xa6220014, 0x8ec30068,
-0x8ee40478, 0x8ee5047c, 0x24020004, 0xafa20010, 0x8ec20068, 0x2203021,
-0x24070020, 0xafa20014, 0x8ec20008, 0x31940, 0x604821, 0xafa20018,
-0x8ec200a8, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809,
-0x832021, 0x54400018, 0xa2c000ed, 0x97ad0046, 0xa63e000e, 0xa62d000a,
-0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x24842e20, 0x3c050006,
-0xafa20014, 0x8ec60068, 0x34a5f00b, 0xc0028eb, 0x2203821, 0x93a20067,
-0x104000b6, 0x0, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0x340e8100,
-0x10000083, 0xa6ae000c, 0x8fae005c, 0x8fad0054, 0xadae0000, 0x8ec202c4,
-0x8ec30068, 0x2442ffff, 0xaec202c4, 0x8ec202c4, 0x24630001, 0x306303ff,
-0x26c20060, 0x15a20006, 0xaec30068, 0x8ec202c0, 0x2442ffff, 0xaec202c0,
-0x10000005, 0x8ec202c0, 0x8ec202bc, 0x2442ffff, 0xaec202bc, 0x8ec202bc,
-0x8ec20048, 0x24420001, 0xaec20048, 0x8f430240, 0x43102b, 0x54400090,
-0xafa00034, 0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120,
-0x24020013, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x24070008,
-0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842dac,
-0xafb10010, 0xafa00014, 0x8ec60068, 0x8f470228, 0x3c050009, 0xc0028eb,
-0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821,
-0x1000000a, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268,
-0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x8ec20268, 0x8ec2027c,
-0x24420001, 0xaec2027c, 0x8ec2027c, 0x10000062, 0xafa00034, 0x962d000a,
-0xafad0044, 0x9622000e, 0xa633000a, 0x8fae0074, 0x11c00006, 0x305effff,
-0x34420400, 0xa622000e, 0x8fad006c, 0xd1402, 0xa6220014, 0x8ec30068,
-0x8ee40478, 0x8ee5047c, 0x24020004, 0xafa20010, 0x8ec20068, 0x2203021,
-0x24070020, 0xafa20014, 0x8ec20008, 0x31940, 0x604821, 0xafa20018,
-0x8ec200a8, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809,
-0x832021, 0x1440001f, 0x3c04001f, 0x97ae0046, 0xa63e000e, 0xa62e000a,
-0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x24842e20, 0x3c050006,
-0xafa20014, 0x8ec60068, 0x34a5f00d, 0xc0028eb, 0x2203821, 0x93a20067,
-0x10400032, 0x340d8100, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0xa6ad000c,
-0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 0xa6a2000e, 0x9622000e,
-0x3042fdff, 0x10000025, 0xa622000e, 0x8ec202c4, 0x8fae002c, 0x3484ffff,
-0x1d37021, 0x2442ffff, 0xafae002c, 0xaec202c4, 0x8ec202c4, 0x8ec302bc,
-0x24020001, 0x8e202b, 0xa2c200ed, 0x2463ffff, 0xaec302bc, 0x10800004,
-0x8ec202bc, 0x8ec20540, 0x1c27023, 0xafae002c, 0x8fad0034, 0x8fae0054,
-0x1b36823, 0xafad0034, 0x8fad005c, 0xadcd0000, 0x8ec20068, 0xa3a0004f,
-0x8ec30048, 0x24420001, 0x304203ff, 0x24630001, 0xaec20068, 0xaec30048,
-0x8fae0034, 0x15c0fe9d, 0x0, 0x8fad0034, 0x11a0001f, 0x0,
-0xaecd00f0, 0x8fae002c, 0xaece00f4, 0xaed500f8, 0x93a20067, 0x10400004,
-0x0, 0x8ec200f8, 0x24420004, 0xaec200f8, 0x8fad006c, 0x8ec20068,
-0xaecd00fc, 0x8fae003c, 0xaece0100, 0x8f430280, 0x24420001, 0x304203ff,
-0x14620006, 0x0, 0x8ec202b8, 0x24420001, 0xaec202b8, 0x10000016,
-0x8ec202b8, 0x8ec202b0, 0x24420001, 0xaec202b0, 0x10000011, 0x8ec202b0,
-0x8fad006c, 0x31a4ffff, 0x2484fffc, 0x801821, 0x8ec401b8, 0x8ec501bc,
-0x3c060001, 0x8cc633b0, 0x1021, 0xa32821, 0xa3382b, 0x822021,
-0x872021, 0xaec401b8, 0xc0f809, 0xaec501bc, 0x8fbf0088, 0x8fbe0084,
-0x8fb50080, 0x8fb3007c, 0x8fb10078, 0x3e00008, 0x27bd0090, 0x3e00008,
-0x0, 0x27bdff90, 0xafbf0068, 0xafbe0064, 0xafb50060, 0xafb3005c,
-0xafb10058, 0x92c200ed, 0xafa0002c, 0x10400007, 0xa3a00037, 0x8ecf00fc,
-0x8ec800f0, 0x8ec900f4, 0x8ed500f8, 0x100000d1, 0xafaf003c, 0x3c020001,
-0x8c4233b8, 0x40f809, 0x27a40020, 0x104001ae, 0x0, 0x8fa30024,
-0x8fb50020, 0x3068ffff, 0x92a20000, 0x2508fffc, 0x2a04821, 0x30420001,
-0x1040001a, 0xafa3003c, 0x8ec2011c, 0x3c03ffff, 0x431024, 0x14400015,
-0x2402ffff, 0x8ea30000, 0x14620005, 0x2a02021, 0x96a30004, 0x3402ffff,
-0x1062000e, 0x0, 0xafa80048, 0xc0022ad, 0xafa9004c, 0x304200ff,
-0x8fa80048, 0x14400007, 0x8fa9004c, 0x3c020001, 0x8c4233b0, 0x40f809,
-0x0, 0x1000018c, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff,
-0x431024, 0x3c03ffff, 0x432824, 0x14a00003, 0xafa20024, 0x10000053,
-0x1821, 0x3c020080, 0xa21024, 0x50400007, 0x3c040040, 0x8ec202e4,
-0x24420001, 0xaec202e4, 0x8ec202e4, 0x10000049, 0x24030001, 0x3c070004,
-0x3c0e0001, 0x3c0d0002, 0x3c060010, 0x3c0c0008, 0x8ec20178, 0x3c0b0020,
-0x340a8000, 0x24420001, 0xaec20178, 0x8ec20178, 0x851824, 0x10670021,
-0xe3102b, 0x14400007, 0x0, 0x106e0011, 0x0, 0x106d0015,
-0x0, 0x10000030, 0x42042, 0x10660023, 0xc3102b, 0x14400005,
-0x0, 0x106c0019, 0x0, 0x10000028, 0x42042, 0x106b0021,
-0x0, 0x10000024, 0x42042, 0x8ec2012c, 0x24420001, 0xaec2012c,
-0x8ec2012c, 0x1000001e, 0x42042, 0x8ec202d4, 0x24420001, 0xaec202d4,
-0x8ec202d4, 0x10000018, 0x42042, 0x8ec202d8, 0x24420001, 0xaec202d8,
-0x8ec202d8, 0x10000012, 0x42042, 0x8ec202dc, 0x24420001, 0xaec202dc,
-0x8ec202dc, 0x1000000c, 0x42042, 0x8ec20128, 0x24420001, 0xaec20128,
-0x8ec20128, 0x10000006, 0x42042, 0x8ec202e0, 0x24420001, 0xaec202e0,
-0x8ec202e0, 0x42042, 0x148affc6, 0x851824, 0x24030001, 0x8f420260,
-0x48102b, 0x10400019, 0x306400ff, 0x8f8200e0, 0xafa20010, 0x8f8200e4,
-0x3c040001, 0x24842dfc, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050006,
-0x34a5f003, 0xafa80048, 0xc0028eb, 0xafa9004c, 0x8ec30150, 0x8faf003c,
-0x3c020100, 0x24040001, 0x1e27825, 0x24630001, 0xafaf003c, 0xaec30150,
-0x8ec20150, 0x8fa9004c, 0x8fa80048, 0x10800025, 0x0, 0x8f420218,
-0x30420800, 0x14400021, 0x3c020180, 0x8faf003c, 0x1e21024, 0x104000fe,
-0x1001821, 0x8ec20174, 0x24420001, 0xaec20174, 0x8ec20174, 0x100000f8,
-0x1001821, 0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842e08,
-0xafa20014, 0x8ec6003c, 0x8ec70044, 0x3c050006, 0x34a5f002, 0xafa80048,
-0xc0028eb, 0xafa9004c, 0x8ec202b4, 0x2403ffbf, 0x283a024, 0x24420001,
-0xaec202b4, 0x8ec202b4, 0x8fa80048, 0x100000c2, 0x8fa9004c, 0x8f420218,
-0x30420400, 0x54400001, 0x25080004, 0x96e20460, 0x48102b, 0x10400003,
-0x0, 0x3c0f8000, 0xafaf002c, 0x110000d2, 0x3c02ffff, 0x8faf003c,
-0x1e21024, 0xafa20044, 0x8ec20068, 0x8f430280, 0x24420001, 0x304203ff,
-0x106200ad, 0x0, 0x8faf002c, 0x11e00014, 0x0, 0x8ec3005c,
-0x8ec20060, 0x10620009, 0x26cb0060, 0x8ec60060, 0x8ec30060, 0x21140,
-0x24424dc0, 0x2e28821, 0x24630001, 0x10000014, 0x306a00ff, 0x92c20064,
-0x1440ffc4, 0x0, 0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8,
-0x8ec3003c, 0x8ec20044, 0x1062ffbc, 0x26cb0044, 0x8ec60044, 0xafa0002c,
-0x8ec30044, 0x21140, 0x24420dc0, 0x2e28821, 0x24630001, 0x306a01ff,
-0x96e20462, 0x30420010, 0x10400017, 0x0, 0x96a2000c, 0x340f8100,
-0x144f0013, 0x0, 0x92c200ed, 0x14400010, 0x0, 0x96a2000e,
-0xa6220016, 0x8ea20008, 0x8ea30004, 0x8ea40000, 0x2508fffc, 0xaea2000c,
-0xaea30008, 0xaea40004, 0x9622000e, 0x25290004, 0x240f0001, 0xa3af0037,
-0x34420200, 0xa622000e, 0x9623000a, 0x68102b, 0x14400002, 0x3073fff8,
-0x1009821, 0x92c300ed, 0x2e62003d, 0x2c630001, 0x621824, 0x1060000f,
-0x260f021, 0x9523000c, 0x24020800, 0x5462000c, 0xae290018, 0x91220017,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600004,
-0xae290018, 0x95220010, 0x245e000e, 0xae290018, 0x92c300ed, 0x8e240000,
-0x8e250004, 0x8faf002c, 0x2402000b, 0xafa20010, 0x3182b, 0x31ec0,
-0xcf1025, 0x431025, 0xafa20014, 0x8ec20004, 0xafa20018, 0x8ec200a8,
-0x3c03821, 0x1203021, 0xafa80048, 0xafa9004c, 0xafaa0050, 0x40f809,
-0xafab0054, 0x8fa80048, 0x8fa9004c, 0x8faa0050, 0x8fab0054, 0x1440001d,
-0x3c050006, 0x3c040001, 0x24842e14, 0x8e220018, 0x34a5f009, 0xafa20010,
-0x8e220000, 0x8e230004, 0x2203021, 0x3c03821, 0xafa80048, 0xafa9004c,
-0xc0028eb, 0xafa30014, 0x93a20037, 0x8fa80048, 0x8fa9004c, 0x1040002a,
-0x340f8100, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0xa6af000c, 0xaea20000,
-0xaea30004, 0xaea40008, 0x96220016, 0x10000020, 0xa6a2000e, 0x8faf0044,
-0x11e00007, 0x0, 0x8faf003c, 0x9623000e, 0xf1402, 0x34630400,
-0xa6220014, 0xa623000e, 0x56680008, 0x1334821, 0x9622000e, 0xa628000a,
-0x4021, 0x34420004, 0xa622000e, 0x1000000c, 0xa2c000ed, 0x3c03001f,
-0x3463ffff, 0x24020001, 0x69182b, 0xa633000a, 0x10600003, 0xa2c200ed,
-0x8ec20540, 0x1224823, 0x1134023, 0xafa0002c, 0x1500ff4f, 0xad6a0000,
-0x1100001b, 0x0, 0xaec800f0, 0xaec900f4, 0xaed500f8, 0x93a20037,
-0x10400004, 0x0, 0x8ec200f8, 0x24420004, 0xaec200f8, 0x8faf003c,
-0x8ec20068, 0xaecf00fc, 0x8f430280, 0x24420001, 0x14620006, 0x0,
-0x8ec202b8, 0x24420001, 0xaec202b8, 0x10000016, 0x8ec202b8, 0x8ec202b0,
-0x24420001, 0xaec202b0, 0x10000011, 0x8ec202b0, 0x8faf003c, 0x31e4ffff,
-0x2484fffc, 0x801821, 0x8ec401b8, 0x8ec501bc, 0x3c060001, 0x8cc633b0,
-0x1021, 0xa32821, 0xa3382b, 0x822021, 0x872021, 0xaec401b8,
-0xc0f809, 0xaec501bc, 0x8fbf0068, 0x8fbe0064, 0x8fb50060, 0x8fb3005c,
-0x8fb10058, 0x3e00008, 0x27bd0070, 0x3e00008, 0x0, 0x27bdffd8,
-0xafbf0024, 0xafb10020, 0x8ec30040, 0x8ec20038, 0x1062004d, 0x0,
-0x8ec30038, 0x8ec20040, 0x623823, 0x4e20001, 0x24e70200, 0x8ec30044,
-0x8ec20040, 0x43102b, 0x14400004, 0x24020200, 0x8ec30040, 0x10000005,
-0x431823, 0x8ec20044, 0x8ec30040, 0x431023, 0x2443ffff, 0xe08821,
-0x71102a, 0x54400001, 0x608821, 0x8ec90040, 0x8ee40458, 0x8ee5045c,
-0x8ec60040, 0x113940, 0x24080002, 0xafa80010, 0x8ec80040, 0x94940,
-0x1201821, 0x1021, 0xafa80014, 0x8ec80010, 0xa32821, 0xa3482b,
-0x822021, 0x892021, 0x63140, 0xafa80018, 0x8ec200a4, 0x24c60dc0,
-0x40f809, 0x2e63021, 0x1440000e, 0x24030040, 0x8ec20040, 0xafa20010,
-0x8ec20044, 0x3c040001, 0x24842e2c, 0xafa20014, 0x8ec60038, 0x8ec7003c,
-0x3c050007, 0xc0028eb, 0x34a5f001, 0x10000010, 0x0, 0x8ec20030,
-0x24420001, 0x50430003, 0x1021, 0x8ec20030, 0x24420001, 0xaec20030,
-0x8ec20030, 0x21080, 0x571021, 0xac510cc0, 0x8ec20040, 0x511021,
-0x304201ff, 0xaec20040, 0x8ec30040, 0x8ec20038, 0x14620017, 0x0,
-0x8ec20000, 0x10400007, 0x2403fdff, 0xaf80004c, 0x8f82004c, 0x1040fffd,
-0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd,
-0x0, 0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003,
-0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020,
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024,
-0xafb10020, 0x8ec30058, 0x8ec20054, 0x1062004d, 0x0, 0x8ec30054,
-0x8ec20058, 0x623823, 0x4e20001, 0x24e70100, 0x8ec30060, 0x8ec20058,
-0x43102b, 0x14400004, 0x24020100, 0x8ec30058, 0x10000005, 0x431823,
-0x8ec20060, 0x8ec30058, 0x431023, 0x2443ffff, 0xe08821, 0x71102a,
-0x54400001, 0x608821, 0x8ec90058, 0x8ee40468, 0x8ee5046c, 0x8ec60058,
-0x113940, 0x24080003, 0xafa80010, 0x8ec80058, 0x94940, 0x1201821,
-0x1021, 0xafa80014, 0x8ec80010, 0xa32821, 0xa3482b, 0x822021,
-0x892021, 0x63140, 0xafa80018, 0x8ec200a4, 0x24c64dc0, 0x40f809,
-0x2e63021, 0x1440000e, 0x24030040, 0x8ec20058, 0xafa20010, 0x8ec20060,
-0x3c040001, 0x24842e38, 0xafa20014, 0x8ec60054, 0x8ec7005c, 0x3c050007,
-0xc0028eb, 0x34a5f010, 0x10000010, 0x0, 0x8ec20030, 0x24420001,
-0x50430003, 0x1021, 0x8ec20030, 0x24420001, 0xaec20030, 0x8ec20030,
-0x21080, 0x571021, 0xac510cc0, 0x8ec20058, 0x511021, 0x304200ff,
-0xaec20058, 0x8ec30058, 0x8ec20054, 0x14620017, 0x0, 0x8ec20000,
-0x10400007, 0x2403feff, 0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0,
-0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 0x0,
-0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003, 0x0,
-0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008,
-0x27bd0028, 0x3e00008, 0x0, 0x8f820120, 0x8ec300e8, 0x8f820124,
-0x8f860128, 0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ec200e8,
-0x24420001, 0xaec200e8, 0x8ec200e8, 0x8ec400e8, 0x8ec300e4, 0x210c0,
-0x24426fc0, 0x14830007, 0x2e22821, 0x8f820128, 0x24420020, 0xaf820128,
-0x8f820128, 0x10000011, 0xaca00000, 0x8ec200e8, 0x24030040, 0x24420001,
-0x50430003, 0x1021, 0x8ec200e8, 0x24420001, 0x220c0, 0x2e41021,
-0x8c426fc4, 0x8f830128, 0x21140, 0x621821, 0x2e41021, 0xaf830128,
-0xac406fc0, 0x8cc20018, 0x2443fffe, 0x2c620018, 0x1040000a, 0x31080,
-0x3c010001, 0x220821, 0x8c222e48, 0x400008, 0x0, 0x24020001,
-0x3c010001, 0x370821, 0xac2281e8, 0x3e00008, 0x0, 0x3e00008,
-0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044,
-0xafb10040, 0x8f830128, 0x8f820124, 0x106201e1, 0x0, 0x8f9e0128,
-0x8f820128, 0x24420020, 0xaf820128, 0x8fc40018, 0x8f820128, 0x2402000b,
-0x1482018f, 0x24020002, 0x8fc3001c, 0x97c20016, 0x3064ffff, 0xafc20014,
-0x3c028000, 0x621024, 0xafc4001c, 0xafa2002c, 0x8fab002c, 0x3c020800,
-0x11600004, 0x622824, 0x41140, 0x10000003, 0x24424dc0, 0x41140,
-0x24420dc0, 0x2e2a821, 0x96a2000e, 0x3043fffc, 0x30420400, 0x10400003,
-0xa6a3000e, 0x10000137, 0x8821, 0x10a00004, 0x8821, 0x97d10016,
-0x10000132, 0x0, 0x8eab0018, 0xafab0034, 0x9563000c, 0x96eb0462,
-0x24020800, 0x1462012b, 0xafab003c, 0x8fab0034, 0x2573000e, 0x8fab003c,
-0x31620002, 0x1040003f, 0x3c030020, 0x8ec70540, 0x263102b, 0x14400002,
-0x2604821, 0x2674823, 0x25220014, 0x43102b, 0x10400027, 0x24030005,
-0x91220000, 0x3042000f, 0x14430024, 0x1202021, 0x952a0000, 0x25290002,
-0x95280000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002,
-0x95250000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002,
-0x95240000, 0x25290002, 0x1485021, 0x1475021, 0x1465021, 0x1455021,
-0x1435021, 0x1425021, 0x95220000, 0x95230002, 0x1445021, 0x1425021,
-0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff,
-0x10000009, 0x625021, 0x1202021, 0x90850000, 0x3c060020, 0x8ec200ac,
-0x30a5000f, 0x40f809, 0x52840, 0x304affff, 0x3143ffff, 0x50600001,
-0x3403ffff, 0x96a2000e, 0x34420002, 0x10000002, 0xa6a2000e, 0x1821,
-0xa6a30010, 0x8fab003c, 0x31620001, 0x104000e1, 0x0, 0x92620009,
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x106000d9,
-0x3c030020, 0x8fa60034, 0x8ec70540, 0xc3102b, 0x50400001, 0xc73023,
-0x24c2000e, 0x43102b, 0x1040001a, 0xc02021, 0x94c70000, 0x24c60002,
-0x94c50000, 0x24c60002, 0x94c30000, 0x24c60002, 0x94c20000, 0x24c60002,
-0x94c40000, 0x24c60002, 0xe53821, 0xe33821, 0xe23821, 0x94c20000,
-0x94c30002, 0xe43821, 0xe23821, 0xe33821, 0x71c02, 0x30e2ffff,
-0x623821, 0x71c02, 0x30e2ffff, 0x10000006, 0x623821, 0x8ec200ac,
-0x24050007, 0x40f809, 0x3c060020, 0x3047ffff, 0x8fab003c, 0x31620008,
-0x10400003, 0x30e8ffff, 0x1000005b, 0x4821, 0x96620006, 0x30421fff,
-0x10400007, 0x2602821, 0x92620000, 0x96630002, 0x3042000f, 0x21080,
-0x10000051, 0x624823, 0x3c070020, 0x8ec30540, 0xa7102b, 0x50400001,
-0xa32823, 0x24a20014, 0x47102b, 0x10400015, 0xa02021, 0x90a20000,
-0x94a30002, 0x3042000f, 0x21080, 0x623023, 0xafa20020, 0x90a30009,
-0x24a5000c, 0x94a20000, 0x24a50002, 0x94a40000, 0x24a50002, 0xc33021,
-0xc23021, 0x94a20000, 0x94a30002, 0xc43021, 0xc23021, 0x1000002d,
-0xc33021, 0x24a50002, 0xa7102b, 0x50400001, 0xa32823, 0x94a60000,
-0x802821, 0xa7102b, 0x50400001, 0xa32823, 0x90a20000, 0x24850009,
-0x3042000f, 0x21080, 0xc23023, 0xafa20020, 0xa7102b, 0x50400001,
-0xa32823, 0x90a20000, 0x2485000c, 0xc23021, 0xa7102b, 0x50400001,
-0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001,
-0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001,
-0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001,
-0xa32823, 0x94a20000, 0xc23021, 0x61c02, 0x30c2ffff, 0x623021,
-0x61402, 0x30c3ffff, 0x431021, 0x3049ffff, 0x96a2000e, 0x30420004,
-0x10400041, 0x0, 0x8f420218, 0x30420400, 0x1040003d, 0x3c070020,
-0x97c2000e, 0x8fc30008, 0x8ec60540, 0x621821, 0x2463fffc, 0x67102b,
-0x50400001, 0x661823, 0x602821, 0x24a20004, 0x47102b, 0x5040000a,
-0xa7102b, 0x90a20000, 0x90a40001, 0x90a30002, 0x21200, 0x441021,
-0x90a40003, 0x31a00, 0x10000017, 0x431021, 0x50400001, 0xa62823,
-0x90a20000, 0x24a50001, 0x22200, 0xa7102b, 0x50400001, 0xa62823,
-0x90a20000, 0x24a50001, 0x822021, 0xa7102b, 0x50400001, 0xa62823,
-0x90a20000, 0x24a50001, 0x21200, 0x822021, 0xa7102b, 0x50400001,
-0xa62823, 0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 0x622021,
-0x41402, 0x3083ffff, 0x431021, 0x3042ffff, 0x1024021, 0x81c02,
-0x3102ffff, 0x624021, 0x81c02, 0x3102ffff, 0x624021, 0x3108ffff,
-0x8fc20014, 0x488823, 0x111402, 0x2228821, 0x2298821, 0x111402,
-0x2228821, 0x3231ffff, 0x52200001, 0x3411ffff, 0x96a2000e, 0x34420001,
-0xa6a2000e, 0x96a2000e, 0x24080002, 0x30420004, 0x10400002, 0xa6b10012,
-0x24080004, 0x8ec90068, 0x8ee40478, 0x8ee5047c, 0xafa80010, 0x8ec80068,
-0x8fab002c, 0x2a03021, 0x24070020, 0x10b4025, 0xafa80014, 0x8ec80008,
-0x94940, 0x1201821, 0xafa80018, 0x8ec800a8, 0x1021, 0xa32821,
-0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000e, 0x0,
-0x8f820120, 0xafa20010, 0x8f820128, 0x3c040001, 0x24842ea8, 0xafa20014,
-0x8fc6001c, 0x8f870124, 0x3c050008, 0xc0028eb, 0x34a50001, 0x1000005f,
-0x0, 0x8ec20068, 0x24420001, 0x304203ff, 0xaec20068, 0x8fab002c,
-0x11600006, 0x0, 0x8ec202c0, 0x2442ffff, 0xaec202c0, 0x10000005,
-0x8ec202c0, 0x8ec202bc, 0x2442ffff, 0xaec202bc, 0x8ec202bc, 0x8ec202c4,
-0x2442ffff, 0xaec202c4, 0x1000004a, 0x8ec202c4, 0x14820005, 0x24020004,
-0x8ec20048, 0x24420001, 0x10000044, 0xaec20048, 0x14820036, 0x38830011,
-0x97c2001e, 0xafc2001c, 0x8ec20048, 0x24420001, 0xaec20048, 0x8f430240,
-0x43102b, 0x14400039, 0x24070008, 0x8ed10068, 0x8ee40490, 0x8ee50494,
-0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014, 0xafa30018,
-0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001,
-0x24842dac, 0xafb10010, 0xafa00014, 0x8ec60068, 0x8f470228, 0x3c050009,
-0xc0028eb, 0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001,
-0x370821, 0x1000000a, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0,
-0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x8ec20268,
-0x8ec2027c, 0x24420001, 0xaec2027c, 0x1000000d, 0x8ec2027c, 0x2c630001,
-0x38820013, 0x2c420001, 0x621825, 0x14600004, 0x24020001, 0x24020012,
-0x14820004, 0x24020001, 0x3c010001, 0x370821, 0xac2281e8, 0x8fbf0050,
-0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb10040, 0x3e00008, 0x27bd0058,
-0x3e00008, 0x0, 0x0, 0x0, 0x8ec20538, 0xaf8200c0,
-0x8ec20538, 0xaf8200c4, 0x8ec20538, 0xaf8200c8, 0x8ec20534, 0xaf8200d0,
-0x8ec20534, 0xaf8200d4, 0x8ec20534, 0x3e00008, 0xaf8200d8, 0x27bdffe8,
-0x27840208, 0x27450200, 0xafbf0010, 0xc00297e, 0x24060008, 0x8f420204,
-0xc003c3a, 0xaf820210, 0x24040001, 0x8f460248, 0x24020004, 0x3c010001,
-0xac2232ac, 0xc004680, 0x24050004, 0x3c020001, 0x8c4232a8, 0x30420001,
-0x10400007, 0x24020001, 0x3c010001, 0xac2232ac, 0x24040001, 0x24050001,
-0xc004680, 0x3c06601b, 0x8ec20548, 0x8ec4054c, 0x8ec30550, 0x3c010001,
-0xac2032a4, 0x3c010001, 0xac2032bc, 0x21640, 0x42140, 0x34840403,
-0x441025, 0x31bc0, 0x431025, 0xaf82021c, 0x8fbf0010, 0x3e00008,
-0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010,
-0xafa00014, 0x8f860200, 0x3c040001, 0x24842f7c, 0xc0028eb, 0x3821,
-0x8ec20368, 0x24420001, 0xaec20368, 0x8ec20368, 0x8f830200, 0x3c023f00,
-0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8,
-0xafbf0020, 0xafb3001c, 0xafb10018, 0x8f910220, 0x8ec202fc, 0x24420001,
-0xaec202fc, 0x8ec202fc, 0x8ec30310, 0x3c020001, 0x8c4232bc, 0x3c040001,
-0x24842f88, 0xafa20014, 0xafa30010, 0x8ec70314, 0x3c050008, 0xc0028eb,
-0x2203021, 0x3c024000, 0x2221024, 0x104000e5, 0x3c040100, 0x8ec20314,
-0x24420001, 0xaec20314, 0x8ec20314, 0x8f820220, 0x3c0308ff, 0x3463ffff,
-0x431024, 0x34420004, 0xaf820220, 0x8f8200e0, 0x8f8300c4, 0x3c02001f,
-0x3442ffff, 0x24690008, 0x49102b, 0x10400003, 0x0, 0x8ec20540,
-0x1224823, 0x8f8700c8, 0x8f850120, 0x8f840124, 0x10000005, 0x5821,
-0x8ec20534, 0x82102b, 0x50400001, 0x27644800, 0x10a40010, 0x316200ff,
-0x8c820018, 0x38430007, 0x2c630001, 0x3842000b, 0x2c420001, 0x621825,
-0x5060fff3, 0x24840020, 0x8ec20328, 0x240b0001, 0x24420001, 0xaec20328,
-0x8ec20328, 0x8c870008, 0x316200ff, 0x14400078, 0x0, 0x92c200ed,
-0x14400075, 0x0, 0x8f8500e4, 0x8f8200e0, 0x2403fff8, 0x433024,
-0xc51023, 0x218c3, 0x4620001, 0x24630100, 0x8f8a00c4, 0x10600005,
-0x24020001, 0x10620009, 0x0, 0x10000021, 0x0, 0x8ec20318,
-0x1403821, 0x24420001, 0xaec20318, 0x10000060, 0x8ec20318, 0x8ec2031c,
-0x24420001, 0xaec2031c, 0x8ca70000, 0x8ec20540, 0x8ec3031c, 0x1471823,
-0x43102b, 0x10400004, 0x2c62233f, 0x8ec20540, 0x621821, 0x2c62233f,
-0x14400051, 0x3c020100, 0xaca20004, 0x8f8200e8, 0x24420008, 0xaf8200e8,
-0x8f8200e8, 0x8f8200e4, 0x1403821, 0x24420008, 0xaf8200e4, 0x10000046,
-0x8f8200e4, 0x8ec20320, 0x24420001, 0xaec20320, 0x8ca80000, 0x8ec20540,
-0x8ec30320, 0x1092023, 0x44102b, 0x10400003, 0x0, 0x8ec20540,
-0x822021, 0x8ec20544, 0x44102b, 0x10400003, 0x3c030100, 0x10000034,
-0x1003821, 0x8ca20004, 0x431025, 0xaca20004, 0x8f8200e4, 0x24450008,
-0xaf8500e4, 0x8f8500e4, 0x10a60025, 0x3c080100, 0x8ec20174, 0x24420001,
-0xaec20174, 0x8ca20004, 0x8ec30174, 0x481024, 0x1440000e, 0x0,
-0x8ca30000, 0x8ec20540, 0x692023, 0x44102b, 0x10400003, 0x0,
-0x8ec20540, 0x822021, 0x8ec20544, 0x44102b, 0x10400006, 0x0,
-0x603821, 0x8ec20544, 0x44102b, 0x1440000a, 0x0, 0x8ca20004,
-0x481025, 0xaca20004, 0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4,
-0x14a6ffdf, 0x0, 0x14a60005, 0x0, 0x1403821, 0xaf8600e4,
-0x10000003, 0xaf8600e8, 0xaf8500e4, 0xaf8500e8, 0x8f8300c8, 0x8ec20540,
-0x692023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021,
-0x8ec20544, 0x82102b, 0x50400008, 0x5821, 0x8ec20540, 0xe92023,
+0x5040002d, 0xafa0003c, 0x8fae0034, 0x4e102b, 0x50400029, 0xafa0003c,
+0x8ec20050, 0x1c21023, 0xafa2003c, 0x8ecd0050, 0x10000023, 0xafad0034,
+0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842f68, 0xafa20014,
+0x8ec6003c, 0x8ec70044, 0x3c050006, 0xc00290f, 0x34a5f002, 0x8ec202b4,
+0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x10000199, 0x8ec202b4,
+0x8e220018, 0x8fa70034, 0x3c040001, 0x24842f74, 0xafa20010, 0x8e220000,
+0x8e230004, 0x34a5f709, 0x2203021, 0xc00290f, 0xafa30014, 0x8ec20298,
+0x24420001, 0xaec20298, 0x10000189, 0x8ec20298, 0x96e20460, 0x8fae0034,
+0x4e102b, 0x10400004, 0x0, 0x240d0001, 0xa3ad004f, 0x8fae0034,
+0x11c001a0, 0x3c02ffff, 0x8fad006c, 0x1a21024, 0xafa20074, 0x8ec20068,
+0x8f430280, 0x24420001, 0x304203ff, 0x10620176, 0x0, 0x93a2004f,
+0x10400015, 0x0, 0x8ec3005c, 0x8ec20060, 0x1062000a, 0x26ce0060,
+0x8ec60060, 0xafae0054, 0x8ec30060, 0x21140, 0x24424dc0, 0x2e28821,
+0x24630001, 0x10000014, 0x306300ff, 0x92c20064, 0x1440ffb9, 0x0,
+0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, 0x8ec3003c, 0x8ec20044,
+0x1062ffb1, 0x26cd0044, 0x8ec60044, 0xafad0054, 0x8ec30044, 0x21140,
+0x24420dc0, 0x2e28821, 0x24630001, 0x306301ff, 0xafa3005c, 0x8f83012c,
+0x10600011, 0x24040002, 0x8f820124, 0x431023, 0x21143, 0x58400001,
+0x24420040, 0x82102a, 0x1040000a, 0x1021, 0x8f820128, 0x431023,
+0x21143, 0x58400001, 0x24420040, 0x82102a, 0x14400002, 0x24020001,
+0x1021, 0x304200ff, 0x1040ffa3, 0x3c050006, 0x96e20462, 0x30420010,
+0x1040001a, 0x340e8100, 0x96a2000c, 0x144e0017, 0x0, 0x92c200ed,
+0x14400014, 0x0, 0x96a2000e, 0xa6220016, 0x8ea20008, 0x8ea30004,
+0x8fad0034, 0x8ea40000, 0x25adfffc, 0xafad0034, 0xaea2000c, 0xaea30008,
+0xaea40004, 0x9622000e, 0x8fae002c, 0x240d0001, 0xa3ad0067, 0x25ce0004,
+0x34420200, 0xafae002c, 0xa622000e, 0x9627000a, 0x8fae0034, 0xee102b,
+0x14400002, 0x30f3fff8, 0x8fb30034, 0x8e240000, 0x8e250004, 0x8fad002c,
+0x24020007, 0xae2d0018, 0xafa20010, 0xafa60014, 0x8ec20004, 0x8fa6002c,
+0xafa20018, 0x8ec200a8, 0x40f809, 0x2603821, 0x1440001a, 0x3c050006,
+0x3c040001, 0x24842f80, 0x8e220018, 0x34a5f009, 0xafa20010, 0x8e220000,
+0x8e230004, 0x2203021, 0x2603821, 0xc00290f, 0xafa30014, 0x93a20067,
+0x104000fb, 0x0, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0x340e8100,
+0xa6ae000c, 0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 0x100000f0,
+0xa6a2000e, 0x8fad0034, 0x166d0089, 0x0, 0x962e000a, 0xafae0044,
+0x8fae003c, 0x9623000e, 0x1ae1021, 0xa622000a, 0x34620004, 0xa622000e,
+0x8fad0074, 0x11a00006, 0x307effff, 0x34620404, 0xa622000e, 0x8fae006c,
+0xe1402, 0xa6220014, 0x8ec30068, 0x8ee40478, 0x8ee5047c, 0x24020004,
+0xafa20010, 0x8ec20068, 0x2203021, 0x24070020, 0xafa20014, 0x8ec20008,
+0x31940, 0x604821, 0xafa20018, 0x8ec200a8, 0x4021, 0xa92821,
+0xa9182b, 0x882021, 0x40f809, 0x832021, 0x54400018, 0xa2c000ed,
+0x97ad0046, 0xa63e000e, 0xa62d000a, 0x8f820100, 0xafa20010, 0x8f820104,
+0x3c040001, 0x24842f8c, 0x3c050006, 0xafa20014, 0x8ec60068, 0x34a5f00b,
+0xc00290f, 0x2203821, 0x93a20067, 0x104000b6, 0x0, 0x8ea20004,
+0x8ea30008, 0x8ea4000c, 0x340e8100, 0x10000083, 0xa6ae000c, 0x8fae005c,
+0x8fad0054, 0xadae0000, 0x8ec202c4, 0x8ec30068, 0x2442ffff, 0xaec202c4,
+0x8ec202c4, 0x24630001, 0x306303ff, 0x26c20060, 0x15a20006, 0xaec30068,
+0x8ec202c0, 0x2442ffff, 0xaec202c0, 0x10000005, 0x8ec202c0, 0x8ec202bc,
+0x2442ffff, 0xaec202bc, 0x8ec202bc, 0x8ec20048, 0x24420001, 0xaec20048,
+0x8f430240, 0x43102b, 0x54400090, 0xafa00034, 0x8ed10068, 0x8ee40490,
+0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014,
+0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440000b,
+0x24020001, 0x3c040001, 0x24842f0c, 0xafb10010, 0xafa00014, 0x8ec60068,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, 0x14400005,
+0x24020001, 0x3c010001, 0x370821, 0x1000000a, 0xac2281e0, 0x3c010001,
+0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001,
+0xaec20268, 0x8ec20268, 0x8ec2027c, 0x24420001, 0xaec2027c, 0x8ec2027c,
+0x10000062, 0xafa00034, 0x962d000a, 0xafad0044, 0x9622000e, 0xa633000a,
+0x8fae0074, 0x11c00006, 0x305effff, 0x34420400, 0xa622000e, 0x8fad006c,
+0xd1402, 0xa6220014, 0x8ec30068, 0x8ee40478, 0x8ee5047c, 0x24020004,
+0xafa20010, 0x8ec20068, 0x2203021, 0x24070020, 0xafa20014, 0x8ec20008,
+0x31940, 0x604821, 0xafa20018, 0x8ec200a8, 0x4021, 0xa92821,
+0xa9182b, 0x882021, 0x40f809, 0x832021, 0x1440001f, 0x3c04001f,
+0x97ae0046, 0xa63e000e, 0xa62e000a, 0x8f820100, 0xafa20010, 0x8f820104,
+0x3c040001, 0x24842f8c, 0x3c050006, 0xafa20014, 0x8ec60068, 0x34a5f00d,
+0xc00290f, 0x2203821, 0x93a20067, 0x10400032, 0x340d8100, 0x8ea20004,
+0x8ea30008, 0x8ea4000c, 0xa6ad000c, 0xaea20000, 0xaea30004, 0xaea40008,
+0x96220016, 0xa6a2000e, 0x9622000e, 0x3042fdff, 0x10000025, 0xa622000e,
+0x8ec202c4, 0x8fae002c, 0x3484ffff, 0x1d37021, 0x2442ffff, 0xafae002c,
+0xaec202c4, 0x8ec202c4, 0x8ec302bc, 0x24020001, 0x8e202b, 0xa2c200ed,
+0x2463ffff, 0xaec302bc, 0x10800004, 0x8ec202bc, 0x8ec20540, 0x1c27023,
+0xafae002c, 0x8fad0034, 0x8fae0054, 0x1b36823, 0xafad0034, 0x8fad005c,
+0xadcd0000, 0x8ec20068, 0xa3a0004f, 0x8ec30048, 0x24420001, 0x304203ff,
+0x24630001, 0xaec20068, 0xaec30048, 0x8fae0034, 0x15c0fe86, 0x0,
+0x8fad0034, 0x11a0001f, 0x0, 0xaecd00f0, 0x8fae002c, 0xaece00f4,
+0xaed500f8, 0x93a20067, 0x10400004, 0x0, 0x8ec200f8, 0x24420004,
+0xaec200f8, 0x8fad006c, 0x8ec20068, 0xaecd00fc, 0x8fae003c, 0xaece0100,
+0x8f430280, 0x24420001, 0x304203ff, 0x14620006, 0x0, 0x8ec202b8,
+0x24420001, 0xaec202b8, 0x10000016, 0x8ec202b8, 0x8ec202b0, 0x24420001,
+0xaec202b0, 0x10000011, 0x8ec202b0, 0x8fad006c, 0x31a4ffff, 0x2484fffc,
+0x801821, 0x8ec401b8, 0x8ec501bc, 0x3c060001, 0x8cc63510, 0x1021,
+0xa32821, 0xa3382b, 0x822021, 0x872021, 0xaec401b8, 0xc0f809,
+0xaec501bc, 0x8fbf0088, 0x8fbe0084, 0x8fb50080, 0x8fb3007c, 0x8fb10078,
+0x3e00008, 0x27bd0090, 0x3e00008, 0x0, 0x27bdff90, 0xafbf0068,
+0xafbe0064, 0xafb50060, 0xafb3005c, 0xafb10058, 0x92c200ed, 0xafa0002c,
+0x10400007, 0xa3a00037, 0x8ecf00fc, 0x8ec800f0, 0x8ec900f4, 0x8ed500f8,
+0x100000d1, 0xafaf003c, 0x3c020001, 0x8c423518, 0x40f809, 0x27a40020,
+0x104001ae, 0x0, 0x8fa30024, 0x8fb50020, 0x3068ffff, 0x92a20000,
+0x2508fffc, 0x2a04821, 0x30420001, 0x1040001a, 0xafa3003c, 0x8ec2011c,
+0x3c03ffff, 0x431024, 0x14400015, 0x2402ffff, 0x8ea30000, 0x14620005,
+0x2a02021, 0x96a30004, 0x3402ffff, 0x1062000e, 0x0, 0xafa80048,
+0xc0022ad, 0xafa9004c, 0x304200ff, 0x8fa80048, 0x14400007, 0x8fa9004c,
+0x3c020001, 0x8c423510, 0x40f809, 0x0, 0x1000018c, 0x0,
+0x8fa20024, 0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff, 0x432824,
+0x14a00003, 0xafa20024, 0x10000053, 0x1821, 0x3c020080, 0xa21024,
+0x50400007, 0x3c040040, 0x8ec202e4, 0x24420001, 0xaec202e4, 0x8ec202e4,
+0x10000049, 0x24030001, 0x3c070004, 0x3c0e0001, 0x3c0d0002, 0x3c060010,
+0x3c0c0008, 0x8ec20178, 0x3c0b0020, 0x340a8000, 0x24420001, 0xaec20178,
+0x8ec20178, 0x851824, 0x10670021, 0xe3102b, 0x14400007, 0x0,
+0x106e0011, 0x0, 0x106d0015, 0x0, 0x10000030, 0x42042,
+0x10660023, 0xc3102b, 0x14400005, 0x0, 0x106c0019, 0x0,
+0x10000028, 0x42042, 0x106b0021, 0x0, 0x10000024, 0x42042,
+0x8ec2012c, 0x24420001, 0xaec2012c, 0x8ec2012c, 0x1000001e, 0x42042,
+0x8ec202d4, 0x24420001, 0xaec202d4, 0x8ec202d4, 0x10000018, 0x42042,
+0x8ec202d8, 0x24420001, 0xaec202d8, 0x8ec202d8, 0x10000012, 0x42042,
+0x8ec202dc, 0x24420001, 0xaec202dc, 0x8ec202dc, 0x1000000c, 0x42042,
+0x8ec20128, 0x24420001, 0xaec20128, 0x8ec20128, 0x10000006, 0x42042,
+0x8ec202e0, 0x24420001, 0xaec202e0, 0x8ec202e0, 0x42042, 0x148affc6,
+0x851824, 0x24030001, 0x8f420260, 0x48102b, 0x10400019, 0x306400ff,
+0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 0x24842f5c, 0xafa20014,
+0x8fa60020, 0x8fa70024, 0x3c050006, 0x34a5f003, 0xafa80048, 0xc00290f,
+0xafa9004c, 0x8ec30150, 0x8faf003c, 0x3c020100, 0x24040001, 0x1e27825,
+0x24630001, 0xafaf003c, 0xaec30150, 0x8ec20150, 0x8fa9004c, 0x8fa80048,
+0x10800025, 0x0, 0x8f420218, 0x30420800, 0x14400021, 0x3c020180,
+0x8faf003c, 0x1e21024, 0x104000fe, 0x1001821, 0x8ec20174, 0x24420001,
+0xaec20174, 0x8ec20174, 0x100000f8, 0x1001821, 0x8ec2005c, 0xafa20010,
+0x8ec20060, 0x3c040001, 0x24842f68, 0xafa20014, 0x8ec6003c, 0x8ec70044,
+0x3c050006, 0x34a5f002, 0xafa80048, 0xc00290f, 0xafa9004c, 0x8ec202b4,
+0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x8ec202b4, 0x8fa80048,
+0x100000c2, 0x8fa9004c, 0x8f420218, 0x30420400, 0x54400001, 0x25080004,
+0x96e20460, 0x48102b, 0x10400003, 0x0, 0x3c0f8000, 0xafaf002c,
+0x110000d2, 0x3c02ffff, 0x8faf003c, 0x1e21024, 0xafa20044, 0x8ec20068,
+0x8f430280, 0x24420001, 0x304203ff, 0x106200ad, 0x0, 0x8faf002c,
+0x11e00014, 0x0, 0x8ec3005c, 0x8ec20060, 0x10620009, 0x26cb0060,
+0x8ec60060, 0x8ec30060, 0x21140, 0x24424dc0, 0x2e28821, 0x24630001,
+0x10000014, 0x306a00ff, 0x92c20064, 0x1440ffc4, 0x0, 0x8ec202c8,
+0x24420001, 0xaec202c8, 0x8ec202c8, 0x8ec3003c, 0x8ec20044, 0x1062ffbc,
+0x26cb0044, 0x8ec60044, 0xafa0002c, 0x8ec30044, 0x21140, 0x24420dc0,
+0x2e28821, 0x24630001, 0x306a01ff, 0x96e20462, 0x30420010, 0x10400017,
+0x0, 0x96a2000c, 0x340f8100, 0x144f0013, 0x0, 0x92c200ed,
+0x14400010, 0x0, 0x96a2000e, 0xa6220016, 0x8ea20008, 0x8ea30004,
+0x8ea40000, 0x2508fffc, 0xaea2000c, 0xaea30008, 0xaea40004, 0x9622000e,
+0x25290004, 0x240f0001, 0xa3af0037, 0x34420200, 0xa622000e, 0x9623000a,
+0x68102b, 0x14400002, 0x3073fff8, 0x1009821, 0x92c200ed, 0x14400012,
+0x260f021, 0x9523000c, 0x24020800, 0x5462000f, 0xae290018, 0x91220017,
+0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600007,
+0xae290018, 0x95220010, 0x2443000e, 0x73102b, 0x54400001, 0x60f021,
+0xae290018, 0x92c300ed, 0x8e240000, 0x8e250004, 0x8faf002c, 0x2402000b,
+0xafa20010, 0x3182b, 0x31ec0, 0xcf1025, 0x431025, 0xafa20014,
+0x8ec20004, 0xafa20018, 0x8ec200a8, 0x3c03821, 0x1203021, 0xafa80048,
+0xafa9004c, 0xafaa0050, 0x40f809, 0xafab0054, 0x8fa80048, 0x8fa9004c,
+0x8faa0050, 0x8fab0054, 0x1440001d, 0x3c050006, 0x3c040001, 0x24842f80,
+0x8e220018, 0x34a5f009, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021,
+0x3c03821, 0xafa80048, 0xafa9004c, 0xc00290f, 0xafa30014, 0x93a20037,
+0x8fa80048, 0x8fa9004c, 0x1040002a, 0x340f8100, 0x8ea20004, 0x8ea30008,
+0x8ea4000c, 0xa6af000c, 0xaea20000, 0xaea30004, 0xaea40008, 0x96220016,
+0x10000020, 0xa6a2000e, 0x8faf0044, 0x11e00007, 0x0, 0x8faf003c,
+0x9623000e, 0xf1402, 0x34630400, 0xa6220014, 0xa623000e, 0x56680008,
+0x1334821, 0x9622000e, 0xa628000a, 0x4021, 0x34420004, 0xa622000e,
+0x1000000c, 0xa2c000ed, 0x3c03001f, 0x3463ffff, 0x24020001, 0x69182b,
+0xa633000a, 0x10600003, 0xa2c200ed, 0x8ec20540, 0x1224823, 0x1134023,
+0xafa0002c, 0x1500ff4f, 0xad6a0000, 0x1100001b, 0x0, 0xaec800f0,
+0xaec900f4, 0xaed500f8, 0x93a20037, 0x10400004, 0x0, 0x8ec200f8,
+0x24420004, 0xaec200f8, 0x8faf003c, 0x8ec20068, 0xaecf00fc, 0x8f430280,
+0x24420001, 0x14620006, 0x0, 0x8ec202b8, 0x24420001, 0xaec202b8,
+0x10000016, 0x8ec202b8, 0x8ec202b0, 0x24420001, 0xaec202b0, 0x10000011,
+0x8ec202b0, 0x8faf003c, 0x31e4ffff, 0x2484fffc, 0x801821, 0x8ec401b8,
+0x8ec501bc, 0x3c060001, 0x8cc63510, 0x1021, 0xa32821, 0xa3382b,
+0x822021, 0x872021, 0xaec401b8, 0xc0f809, 0xaec501bc, 0x8fbf0068,
+0x8fbe0064, 0x8fb50060, 0x8fb3005c, 0x8fb10058, 0x3e00008, 0x27bd0070,
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 0xafb10020, 0x8ec30040,
+0x8ec20038, 0x1062004d, 0x0, 0x8ec30038, 0x8ec20040, 0x623823,
+0x4e20001, 0x24e70200, 0x8ec30044, 0x8ec20040, 0x43102b, 0x14400004,
+0x24020200, 0x8ec30040, 0x10000005, 0x431823, 0x8ec20044, 0x8ec30040,
+0x431023, 0x2443ffff, 0xe08821, 0x71102a, 0x54400001, 0x608821,
+0x8ec90040, 0x8ee40458, 0x8ee5045c, 0x8ec60040, 0x113940, 0x24080002,
+0xafa80010, 0x8ec80040, 0x94940, 0x1201821, 0x1021, 0xafa80014,
+0x8ec80010, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x63140,
+0xafa80018, 0x8ec200a4, 0x24c60dc0, 0x40f809, 0x2e63021, 0x1440000e,
+0x24030040, 0x8ec20040, 0xafa20010, 0x8ec20044, 0x3c040001, 0x24842f98,
+0xafa20014, 0x8ec60038, 0x8ec7003c, 0x3c050007, 0xc00290f, 0x34a5f001,
+0x10000010, 0x0, 0x8ec20030, 0x24420001, 0x50430003, 0x1021,
+0x8ec20030, 0x24420001, 0xaec20030, 0x8ec20030, 0x21080, 0x571021,
+0xac510cc0, 0x8ec20040, 0x511021, 0x304201ff, 0xaec20040, 0x8ec30040,
+0x8ec20038, 0x14620017, 0x0, 0x8ec20000, 0x10400007, 0x2403fdff,
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0,
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024,
+0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c,
+0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008,
+0x0, 0x27bdffd8, 0xafbf0024, 0xafb10020, 0x8ec30058, 0x8ec20054,
+0x1062004d, 0x0, 0x8ec30054, 0x8ec20058, 0x623823, 0x4e20001,
+0x24e70100, 0x8ec30060, 0x8ec20058, 0x43102b, 0x14400004, 0x24020100,
+0x8ec30058, 0x10000005, 0x431823, 0x8ec20060, 0x8ec30058, 0x431023,
+0x2443ffff, 0xe08821, 0x71102a, 0x54400001, 0x608821, 0x8ec90058,
+0x8ee40468, 0x8ee5046c, 0x8ec60058, 0x113940, 0x24080003, 0xafa80010,
+0x8ec80058, 0x94940, 0x1201821, 0x1021, 0xafa80014, 0x8ec80010,
+0xa32821, 0xa3482b, 0x822021, 0x892021, 0x63140, 0xafa80018,
+0x8ec200a4, 0x24c64dc0, 0x40f809, 0x2e63021, 0x1440000e, 0x24030040,
+0x8ec20058, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842fa4, 0xafa20014,
+0x8ec60054, 0x8ec7005c, 0x3c050007, 0xc00290f, 0x34a5f010, 0x10000010,
+0x0, 0x8ec20030, 0x24420001, 0x50430003, 0x1021, 0x8ec20030,
+0x24420001, 0xaec20030, 0x8ec20030, 0x21080, 0x571021, 0xac510cc0,
+0x8ec20058, 0x511021, 0x304200ff, 0xaec20058, 0x8ec30058, 0x8ec20054,
+0x14620017, 0x0, 0x8ec20000, 0x10400007, 0x2403feff, 0xaf80004c,
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048,
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 0xaf820060,
+0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048,
+0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0,
+0x8f820120, 0x8ec300e8, 0x8f820124, 0x8f860128, 0x24020040, 0x24630001,
+0x50620003, 0x1021, 0x8ec200e8, 0x24420001, 0xaec200e8, 0x8ec200e8,
+0x8ec400e8, 0x8ec300e4, 0x210c0, 0x24426fc0, 0x14830007, 0x2e22821,
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x10000011, 0xaca00000,
+0x8ec200e8, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ec200e8,
+0x24420001, 0x220c0, 0x2e41021, 0x8c426fc4, 0x8f830128, 0x21140,
+0x621821, 0x2e41021, 0xaf830128, 0xac406fc0, 0x8cc20018, 0x2443fffe,
+0x2c620018, 0x1040000a, 0x31080, 0x3c010001, 0x220821, 0x8c222fb0,
+0x400008, 0x0, 0x24020001, 0x3c010001, 0x370821, 0xac2281e8,
+0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffa8, 0xafbf0050,
+0xafbe004c, 0xafb50048, 0xafb30044, 0xafb10040, 0x8f830128, 0x8f820124,
+0x106201e1, 0x0, 0x8f9e0128, 0x8f820128, 0x24420020, 0xaf820128,
+0x8fc40018, 0x8f820128, 0x2402000b, 0x1482018f, 0x24020002, 0x8fc3001c,
+0x97c20016, 0x3064ffff, 0xafc20014, 0x3c028000, 0x621024, 0xafc4001c,
+0xafa2002c, 0x8fab002c, 0x3c020800, 0x11600004, 0x622824, 0x41140,
+0x10000003, 0x24424dc0, 0x41140, 0x24420dc0, 0x2e2a821, 0x96a2000e,
+0x3043fffc, 0x30420400, 0x10400003, 0xa6a3000e, 0x10000137, 0x8821,
+0x10a00004, 0x8821, 0x97d10016, 0x10000132, 0x0, 0x8eab0018,
+0xafab0034, 0x9563000c, 0x96eb0462, 0x24020800, 0x1462012b, 0xafab003c,
+0x8fab0034, 0x2573000e, 0x8fab003c, 0x31620002, 0x1040003f, 0x3c030020,
+0x8ec70540, 0x263102b, 0x14400002, 0x2604821, 0x2674823, 0x25220014,
+0x43102b, 0x10400027, 0x24030005, 0x91220000, 0x3042000f, 0x14430024,
+0x1202021, 0x952a0000, 0x25290002, 0x95280000, 0x25290002, 0x95270000,
+0x25290002, 0x95260000, 0x25290002, 0x95250000, 0x25290002, 0x95230000,
+0x25290002, 0x95220000, 0x25290002, 0x95240000, 0x25290002, 0x1485021,
+0x1475021, 0x1465021, 0x1455021, 0x1435021, 0x1425021, 0x95220000,
+0x95230002, 0x1445021, 0x1425021, 0x1435021, 0xa1c02, 0x3142ffff,
+0x625021, 0xa1c02, 0x3142ffff, 0x10000009, 0x625021, 0x1202021,
+0x90850000, 0x3c060020, 0x8ec200ac, 0x30a5000f, 0x40f809, 0x52840,
+0x304affff, 0x3143ffff, 0x50600001, 0x3403ffff, 0x96a2000e, 0x34420002,
+0x10000002, 0xa6a2000e, 0x1821, 0xa6a30010, 0x8fab003c, 0x31620001,
+0x104000e1, 0x0, 0x92620009, 0x38430006, 0x2c630001, 0x38420011,
+0x2c420001, 0x621825, 0x106000d9, 0x3c030020, 0x8fa60034, 0x8ec70540,
+0xc3102b, 0x50400001, 0xc73023, 0x24c2000e, 0x43102b, 0x1040001a,
+0xc02021, 0x94c70000, 0x24c60002, 0x94c50000, 0x24c60002, 0x94c30000,
+0x24c60002, 0x94c20000, 0x24c60002, 0x94c40000, 0x24c60002, 0xe53821,
+0xe33821, 0xe23821, 0x94c20000, 0x94c30002, 0xe43821, 0xe23821,
+0xe33821, 0x71c02, 0x30e2ffff, 0x623821, 0x71c02, 0x30e2ffff,
+0x10000006, 0x623821, 0x8ec200ac, 0x24050007, 0x40f809, 0x3c060020,
+0x3047ffff, 0x8fab003c, 0x31620008, 0x10400003, 0x30e8ffff, 0x1000005b,
+0x4821, 0x96620006, 0x30421fff, 0x10400007, 0x2602821, 0x92620000,
+0x96630002, 0x3042000f, 0x21080, 0x10000051, 0x624823, 0x3c070020,
+0x8ec30540, 0xa7102b, 0x50400001, 0xa32823, 0x24a20014, 0x47102b,
+0x10400015, 0xa02021, 0x90a20000, 0x94a30002, 0x3042000f, 0x21080,
+0x623023, 0xafa20020, 0x90a30009, 0x24a5000c, 0x94a20000, 0x24a50002,
+0x94a40000, 0x24a50002, 0xc33021, 0xc23021, 0x94a20000, 0x94a30002,
+0xc43021, 0xc23021, 0x1000002d, 0xc33021, 0x24a50002, 0xa7102b,
+0x50400001, 0xa32823, 0x94a60000, 0x802821, 0xa7102b, 0x50400001,
+0xa32823, 0x90a20000, 0x24850009, 0x3042000f, 0x21080, 0xc23023,
+0xafa20020, 0xa7102b, 0x50400001, 0xa32823, 0x90a20000, 0x2485000c,
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002,
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002,
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002,
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0xc23021,
+0x61c02, 0x30c2ffff, 0x623021, 0x61402, 0x30c3ffff, 0x431021,
+0x3049ffff, 0x96a2000e, 0x30420004, 0x10400041, 0x0, 0x8f420218,
+0x30420400, 0x1040003d, 0x3c070020, 0x97c2000e, 0x8fc30008, 0x8ec60540,
+0x621821, 0x2463fffc, 0x67102b, 0x50400001, 0x661823, 0x602821,
+0x24a20004, 0x47102b, 0x5040000a, 0xa7102b, 0x90a20000, 0x90a40001,
+0x90a30002, 0x21200, 0x441021, 0x90a40003, 0x31a00, 0x10000017,
+0x431021, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x22200,
+0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x822021,
+0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x21200,
+0x822021, 0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x822021,
+0x41c02, 0x3082ffff, 0x622021, 0x41402, 0x3083ffff, 0x431021,
+0x3042ffff, 0x1024021, 0x81c02, 0x3102ffff, 0x624021, 0x81c02,
+0x3102ffff, 0x624021, 0x3108ffff, 0x8fc20014, 0x488823, 0x111402,
+0x2228821, 0x2298821, 0x111402, 0x2228821, 0x3231ffff, 0x52200001,
+0x3411ffff, 0x96a2000e, 0x34420001, 0xa6a2000e, 0x96a2000e, 0x24080002,
+0x30420004, 0x10400002, 0xa6b10012, 0x24080004, 0x8ec90068, 0x8ee40478,
+0x8ee5047c, 0xafa80010, 0x8ec80068, 0x8fab002c, 0x2a03021, 0x24070020,
+0x10b4025, 0xafa80014, 0x8ec80008, 0x94940, 0x1201821, 0xafa80018,
+0x8ec800a8, 0x1021, 0xa32821, 0xa3482b, 0x822021, 0x100f809,
+0x892021, 0x1440000e, 0x0, 0x8f820120, 0xafa20010, 0x8f820128,
+0x3c040001, 0x24843010, 0xafa20014, 0x8fc6001c, 0x8f870124, 0x3c050008,
+0xc00290f, 0x34a50001, 0x1000005f, 0x0, 0x8ec20068, 0x24420001,
+0x304203ff, 0xaec20068, 0x8fab002c, 0x11600006, 0x0, 0x8ec202c0,
+0x2442ffff, 0xaec202c0, 0x10000005, 0x8ec202c0, 0x8ec202bc, 0x2442ffff,
+0xaec202bc, 0x8ec202bc, 0x8ec202c4, 0x2442ffff, 0xaec202c4, 0x1000004a,
+0x8ec202c4, 0x14820005, 0x24020004, 0x8ec20048, 0x24420001, 0x10000044,
+0xaec20048, 0x14820036, 0x38830011, 0x97c2001e, 0xafc2001c, 0x8ec20048,
+0x24420001, 0xaec20048, 0x8f430240, 0x43102b, 0x14400039, 0x24070008,
+0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013,
+0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c,
+0x1440000b, 0x24020001, 0x3c040001, 0x24842f0c, 0xafb10010, 0xafa00014,
+0x8ec60068, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021,
+0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000000a, 0xac2281e0,
+0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c,
+0x24420001, 0xaec20268, 0x8ec20268, 0x8ec2027c, 0x24420001, 0xaec2027c,
+0x1000000d, 0x8ec2027c, 0x2c630001, 0x38820013, 0x2c420001, 0x621825,
+0x14600004, 0x24020001, 0x24020012, 0x14820004, 0x24020001, 0x3c010001,
+0x370821, 0xac2281e8, 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044,
+0x8fb10040, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x0,
+0x0, 0x0, 0x8ec20538, 0xaf8200c0, 0x8ec20538, 0xaf8200c4,
+0x8ec20538, 0xaf8200c8, 0x8ec20534, 0xaf8200d0, 0x8ec20534, 0xaf8200d4,
+0x8ec20534, 0x3e00008, 0xaf8200d8, 0x27bdffe8, 0x27840208, 0x27450200,
+0xafbf0010, 0xc0029a2, 0x24060008, 0x8f420204, 0xc003c86, 0xaf820210,
+0x24040001, 0x8f460248, 0x24020004, 0x3c010001, 0xac22340c, 0xc0046cc,
+0x24050004, 0x3c020001, 0x8c423408, 0x30420001, 0x10400007, 0x24020001,
+0x3c010001, 0xac22340c, 0x24040001, 0x24050001, 0xc0046cc, 0x3c06601b,
+0x8ec20548, 0x8ec4054c, 0x8ec30550, 0x3c010001, 0xac203404, 0x3c010001,
+0xac20341c, 0x21640, 0x42140, 0x34840403, 0x441025, 0x31bc0,
+0x431025, 0xaf82021c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0,
+0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200,
+0x3c040001, 0x248430dc, 0xc00290f, 0x3821, 0x8ec20368, 0x24420001,
+0xaec20368, 0x8ec20368, 0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018,
+0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb3001c,
+0xafb10018, 0x8f910220, 0x8ec202fc, 0x24420001, 0xaec202fc, 0x8ec202fc,
+0x8ec30310, 0x3c020001, 0x8c42341c, 0x3c040001, 0x248430e8, 0xafa20014,
+0xafa30010, 0x8ec70314, 0x3c050008, 0xc00290f, 0x2203021, 0x3c024000,
+0x2221024, 0x104000e5, 0x3c040100, 0x8ec20314, 0x24420001, 0xaec20314,
+0x8ec20314, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004,
+0xaf820220, 0x8f8200e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 0x24690008,
+0x49102b, 0x10400003, 0x0, 0x8ec20540, 0x1224823, 0x8f8700c8,
+0x8f850120, 0x8f840124, 0x10000005, 0x5821, 0x8ec20534, 0x82102b,
+0x50400001, 0x27644800, 0x10a40010, 0x316200ff, 0x8c820018, 0x38430007,
+0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 0x24840020,
+0x8ec20328, 0x240b0001, 0x24420001, 0xaec20328, 0x8ec20328, 0x8c870008,
+0x316200ff, 0x14400078, 0x0, 0x92c200ed, 0x14400075, 0x0,
+0x8f8500e4, 0x8f8200e0, 0x2403fff8, 0x433024, 0xc51023, 0x218c3,
+0x4620001, 0x24630100, 0x8f8a00c4, 0x10600005, 0x24020001, 0x10620009,
+0x0, 0x10000021, 0x0, 0x8ec20318, 0x1403821, 0x24420001,
+0xaec20318, 0x10000060, 0x8ec20318, 0x8ec2031c, 0x24420001, 0xaec2031c,
+0x8ca70000, 0x8ec20540, 0x8ec3031c, 0x1471823, 0x43102b, 0x10400004,
+0x2c62233f, 0x8ec20540, 0x621821, 0x2c62233f, 0x14400051, 0x3c020100,
+0xaca20004, 0x8f8200e8, 0x24420008, 0xaf8200e8, 0x8f8200e8, 0x8f8200e4,
+0x1403821, 0x24420008, 0xaf8200e4, 0x10000046, 0x8f8200e4, 0x8ec20320,
+0x24420001, 0xaec20320, 0x8ca80000, 0x8ec20540, 0x8ec30320, 0x1092023,
0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544,
-0x82102b, 0x10400006, 0x316200ff, 0x1440001c, 0x3c02fdff, 0x92c200ed,
-0x14400019, 0x3c02fdff, 0xaf8700c8, 0x8f8400c8, 0x8f8300c4, 0x8ec20540,
-0x832023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021,
-0x8ec20544, 0x2c830001, 0x44102b, 0x431025, 0x10400009, 0x3c02fdff,
-0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0x3c034000, 0x431025,
-0x10000075, 0xaf820220, 0x3442ffff, 0x8ec30324, 0x282a024, 0x24020001,
-0xa2c200ec, 0x24630001, 0xaec30324, 0x1000006c, 0x8ec20324, 0x2241024,
-0x10400013, 0x3c130200, 0x8ec20300, 0x24420001, 0xaec20300, 0x8ec20300,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x441025, 0xaf820220,
-0x3c020004, 0x2221024, 0x14400005, 0x3c130200, 0xc003a65, 0x0,
-0x10000057, 0x0, 0x2331024, 0x50400008, 0x3c130400, 0x8ec20304,
-0x24420001, 0xaec20304, 0xc003a65, 0x8ec20304, 0x10000019, 0x0,
-0x2331024, 0x1040001d, 0x3c020800, 0x8f830224, 0x24021402, 0x14620009,
-0x3c050008, 0x3c040001, 0x24842f94, 0xafa00010, 0xafa00014, 0x8f860224,
-0x34a5ffff, 0xc0028eb, 0x3821, 0x8ec20308, 0x24420001, 0xaec20308,
-0x8ec20308, 0x8f820220, 0x2202021, 0x34420002, 0xc004430, 0xaf820220,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x531025, 0x1000002e,
-0xaf820220, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50403, 0xc0028eb, 0x3821,
-0x3c021000, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50401, 0xc0028eb, 0x3821,
-0x3c022000, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50402, 0xc0028eb, 0x3821,
-0x6210009, 0x3c050008, 0x3c040001, 0x24842f7c, 0xafa00010, 0xafa00014,
-0x8f860220, 0x34a50404, 0xc0028eb, 0x3821, 0x8fbf0020, 0x8fb3001c,
-0x8fb10018, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x3c020001,
-0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c,
-0x1040000f, 0xafb10028, 0x3c040001, 0x24842fa0, 0x3c050008, 0xafa00010,
-0xafa00014, 0x8f860220, 0x34a50498, 0x24020001, 0x3c010001, 0xac2032bc,
-0x3c010001, 0xac2232b0, 0xc0028eb, 0x3821, 0x3c037fff, 0x8f420268,
-0x3463ffff, 0x3c04fdff, 0x431024, 0xaf420268, 0x8ee204a8, 0x3484ffff,
-0x30420002, 0x10400091, 0x284a024, 0x3c040600, 0x8ee204a8, 0x34842000,
-0x2403fffd, 0x431024, 0xaee204a8, 0xafa40020, 0x8ec3002c, 0x240200ff,
-0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821,
-0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x24842f58, 0xafa00010,
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f,
-0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c,
-0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4,
-0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e,
-0xa821, 0x241e000c, 0x8ec8002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c,
-0x24070008, 0xafbe0010, 0xafb30014, 0x840c0, 0x1001821, 0x1021,
-0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0,
-0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006,
-0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0,
-0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x24842f64, 0xafa00010,
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010,
-0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f,
-0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9,
-0x10400017, 0xa821, 0x3c1e0020, 0x24130011, 0x8ec20008, 0x8ee40488,
-0x8ee5048c, 0x8ec3002c, 0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014,
-0xafa20018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2,
-0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0,
-0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842f70, 0xafa00010,
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb,
-0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250,
-0x24420001, 0xaec20250, 0x8ec20250, 0x8fbf0038, 0x8fbe0034, 0x8fb50030,
-0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3c020001, 0x8c4232bc,
-0x27bdffe0, 0x1440000d, 0xafbf0018, 0x3c040001, 0x24842fac, 0x3c050008,
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, 0x24020001, 0x3c010001,
-0xac2232bc, 0xc0028eb, 0x3821, 0x92c2011d, 0x10400008, 0x24040001,
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220,
-0x24040001, 0xc004785, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x0, 0x86102b, 0x50400001, 0x872023, 0xc41023,
-0x24843, 0x125102b, 0x1040001b, 0x91040, 0x824021, 0x88102b,
-0x10400007, 0x1821, 0x94820000, 0x24840002, 0x621821, 0x88102b,
-0x1440fffb, 0x0, 0x602021, 0xc73023, 0xa91023, 0x21040,
-0xc22821, 0xc5102b, 0x10400007, 0x1821, 0x94c20000, 0x24c60002,
-0x621821, 0xc5102b, 0x1440fffb, 0x0, 0x1000000d, 0x832021,
-0x51040, 0x822821, 0x85102b, 0x10400007, 0x1821, 0x94820000,
-0x24840002, 0x621821, 0x85102b, 0x1440fffb, 0x0, 0x602021,
-0x41c02, 0x3082ffff, 0x622021, 0x41c02, 0x3082ffff, 0x622021,
-0x3e00008, 0x3082ffff, 0x3e00008, 0x0, 0x8f820220, 0x34420002,
-0xaf820220, 0x3c020001, 0x8c4254b8, 0x30424000, 0x10400054, 0x24040001,
-0x8f820200, 0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 0x621824,
-0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
-0x1444004d, 0x42040, 0xc4102b, 0x1040fff1, 0x0, 0x8f820200,
-0x451025, 0xaf820200, 0x8f820220, 0x34428000, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1440000f,
-0x0, 0x8f820220, 0x3c03ffff, 0x34637fff, 0x431024, 0xaf820220,
+0x44102b, 0x10400003, 0x3c030100, 0x10000034, 0x1003821, 0x8ca20004,
+0x431025, 0xaca20004, 0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4,
+0x10a60025, 0x3c080100, 0x8ec20174, 0x24420001, 0xaec20174, 0x8ca20004,
+0x8ec30174, 0x481024, 0x1440000e, 0x0, 0x8ca30000, 0x8ec20540,
+0x692023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021,
+0x8ec20544, 0x44102b, 0x10400006, 0x0, 0x603821, 0x8ec20544,
+0x44102b, 0x1440000a, 0x0, 0x8ca20004, 0x481025, 0xaca20004,
+0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, 0x14a6ffdf, 0x0,
+0x14a60005, 0x0, 0x1403821, 0xaf8600e4, 0x10000003, 0xaf8600e8,
+0xaf8500e4, 0xaf8500e8, 0x8f8300c8, 0x8ec20540, 0x692023, 0x44102b,
+0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x82102b,
+0x50400008, 0x5821, 0x8ec20540, 0xe92023, 0x44102b, 0x10400003,
+0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x82102b, 0x10400006,
+0x316200ff, 0x1440001c, 0x3c02fdff, 0x92c200ed, 0x14400019, 0x3c02fdff,
+0xaf8700c8, 0x8f8400c8, 0x8f8300c4, 0x8ec20540, 0x832023, 0x44102b,
+0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x2c830001,
+0x44102b, 0x431025, 0x10400009, 0x3c02fdff, 0x8f820220, 0x3c0308ff,
+0x3463fffb, 0x431024, 0x3c034000, 0x431025, 0x10000075, 0xaf820220,
+0x3442ffff, 0x8ec30324, 0x282a024, 0x24020001, 0xa2c200ec, 0x24630001,
+0xaec30324, 0x1000006c, 0x8ec20324, 0x2241024, 0x10400013, 0x3c130200,
+0x8ec20300, 0x24420001, 0xaec20300, 0x8ec20300, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x441025, 0xaf820220, 0x3c020004, 0x2221024,
+0x14400005, 0x3c130200, 0xc003ab1, 0x0, 0x10000057, 0x0,
+0x2331024, 0x50400008, 0x3c130400, 0x8ec20304, 0x24420001, 0xaec20304,
+0xc003ab1, 0x8ec20304, 0x10000019, 0x0, 0x2331024, 0x1040001d,
+0x3c020800, 0x8f830224, 0x24021402, 0x14620009, 0x3c050008, 0x3c040001,
+0x248430f4, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc00290f,
+0x3821, 0x8ec20308, 0x24420001, 0xaec20308, 0x8ec20308, 0x8f820220,
+0x2202021, 0x34420002, 0xc00447c, 0xaf820220, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x531025, 0x1000002e, 0xaf820220, 0x2221024,
+0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014,
+0x8f860220, 0x34a50403, 0xc00290f, 0x3821, 0x3c021000, 0x2221024,
+0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014,
+0x8f860220, 0x34a50401, 0xc00290f, 0x3821, 0x3c022000, 0x2221024,
+0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014,
+0x8f860220, 0x34a50402, 0xc00290f, 0x3821, 0x6210009, 0x3c050008,
+0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50404,
+0xc00290f, 0x3821, 0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008,
+0x27bd0028, 0x3e00008, 0x0, 0x3c020001, 0x8c42341c, 0x27bdffc0,
+0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0x1040000f, 0xafb10028,
+0x3c040001, 0x24843100, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220,
+0x34a50498, 0x24020001, 0x3c010001, 0xac20341c, 0x3c010001, 0xac223410,
+0xc00290f, 0x3821, 0x3c037fff, 0x8f420268, 0x3463ffff, 0x3c04fdff,
+0x431024, 0xaf420268, 0x8ee204a8, 0x3484ffff, 0x30420002, 0x10400091,
+0x284a024, 0x3c040600, 0x8ee204a8, 0x34842000, 0x2403fffd, 0x431024,
+0xaee204a8, 0xafa40020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020,
+0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f,
+0x0, 0x3c040001, 0x248430b8, 0xafa00010, 0xafa00014, 0x8ec6002c,
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001,
+0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021,
+0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054,
+0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000c,
+0x8ec8002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 0xafbe0010,
+0xafb30014, 0x840c0, 0x1001821, 0x1021, 0x8ec80008, 0xa32821,
+0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8,
+0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054,
+0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011,
+0xaed3002c, 0x3c040001, 0x248430c4, 0xafa00010, 0xafa00014, 0x8f860120,
+0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001,
+0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054,
+0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 0xa821,
+0x3c1e0020, 0x24130011, 0x8ec20008, 0x8ee40488, 0x8ee5048c, 0x8ec3002c,
+0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8,
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054,
+0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 0x1440000f,
+0x0, 0x3c040001, 0x248430d0, 0xafa00010, 0xafa00014, 0x8f860120,
+0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0,
+0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250,
+0x8ec20250, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028,
+0x3e00008, 0x27bd0040, 0x3c020001, 0x8c42341c, 0x27bdffe0, 0x1440000d,
+0xafbf0018, 0x3c040001, 0x2484310c, 0x3c050008, 0xafa00010, 0xafa00014,
+0x8f860220, 0x34a50499, 0x24020001, 0x3c010001, 0xac22341c, 0xc00290f,
+0x3821, 0x92c2011d, 0x10400008, 0x24040001, 0x8f820220, 0x3c0308ff,
+0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24040001, 0xc0047d1,
+0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0,
+0x86102b, 0x50400001, 0x872023, 0xc41023, 0x24843, 0x125102b,
+0x1040001b, 0x91040, 0x824021, 0x88102b, 0x10400007, 0x1821,
+0x94820000, 0x24840002, 0x621821, 0x88102b, 0x1440fffb, 0x0,
+0x602021, 0xc73023, 0xa91023, 0x21040, 0xc22821, 0xc5102b,
+0x10400007, 0x1821, 0x94c20000, 0x24c60002, 0x621821, 0xc5102b,
+0x1440fffb, 0x0, 0x1000000d, 0x832021, 0x51040, 0x822821,
+0x85102b, 0x10400007, 0x1821, 0x94820000, 0x24840002, 0x621821,
+0x85102b, 0x1440fffb, 0x0, 0x602021, 0x41c02, 0x3082ffff,
+0x622021, 0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 0x3082ffff,
+0x3e00008, 0x0, 0x8f820220, 0x34420002, 0xaf820220, 0x3c020001,
+0x8c425618, 0x30424000, 0x10400054, 0x24040001, 0x8f820200, 0x24067fff,
+0x8f830200, 0x30450002, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204,
0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024,
-0x1440000d, 0x0, 0x8f820220, 0x34428000, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002,
-0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1040001b,
-0x1021, 0x8f830220, 0x24020001, 0x10000015, 0x3c04f700, 0x8f820220,
-0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 0x2403fffd, 0x431024,
-0xaf820220, 0x8f820220, 0x3c030300, 0x431024, 0x14400003, 0x0,
-0x10000008, 0x1021, 0x8f820220, 0x34420002, 0xaf820220, 0x8f830220,
-0x24020001, 0x641825, 0xaf830220, 0x3e00008, 0x0, 0x2021,
-0x3c050100, 0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 0x27625000,
-0xaf8200c0, 0x27625000, 0xaf8200c4, 0x27625000, 0xaf8200c8, 0x27625000,
-0xaf8200d0, 0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8, 0x27623000,
-0xaf8200e0, 0x27623000, 0xaf8200e4, 0x27623000, 0xaf8200e8, 0x27622800,
-0xaf8200f0, 0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8, 0x418c0,
-0x24840001, 0x3631021, 0xac453004, 0x3631021, 0xac403000, 0x28820200,
-0x1440fff9, 0x418c0, 0x2021, 0x418c0, 0x24840001, 0x3631021,
-0xac402804, 0x3631021, 0xac402800, 0x28820100, 0x1440fff9, 0x418c0,
-0xaf80023c, 0x24030080, 0x24040100, 0xac600000, 0x24630004, 0x64102b,
-0x5440fffd, 0xac600000, 0x8f830040, 0x3c02f000, 0x621824, 0x3c025000,
-0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008,
-0x24020800, 0x10000008, 0x0, 0x10620004, 0x24020800, 0x10000004,
-0x0, 0x24020700, 0x3c010001, 0xac2232c0, 0x3e00008, 0x0,
-0x27bdffc8, 0xafbf0034, 0xafb50030, 0xafb3002c, 0xafb10028, 0x3c010001,
-0xc00440d, 0xac2032a8, 0x24040001, 0x2821, 0x27a60020, 0x34028000,
-0xc00402a, 0xa7a20020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001,
-0xc003fe8, 0x27a60020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001,
-0xc003fe8, 0x27a60020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050002,
-0xc003fe8, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064,
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050003,
-0xc003fe8, 0x27a6001a, 0x97a20020, 0x10400024, 0x24020001, 0x3c020001,
-0x8c4232a8, 0x97a30018, 0x34420001, 0x3c010001, 0xac2232a8, 0x24020015,
-0x14620004, 0x3402f423, 0x97a3001a, 0x10620018, 0x24020003, 0x97a30018,
-0x24027810, 0x14620014, 0x24020002, 0x97a3001a, 0x24020001, 0x14620010,
-0x24020002, 0x1000000e, 0x24020004, 0x3c020001, 0x8c4232a8, 0x34420008,
-0x3c010001, 0xac2232a8, 0x10000058, 0x24020004, 0x3c020001, 0x8c4232a8,
-0x34420004, 0x3c010001, 0x100000a8, 0xac2232a8, 0x3c010001, 0xac2233dc,
-0x24020e00, 0xaf820238, 0x8f840054, 0x8f820054, 0x24030008, 0x3c010001,
-0xac2332ac, 0x10000002, 0x248401f4, 0x8f820054, 0x821023, 0x2c4201f5,
-0x1440fffc, 0x3c0200c8, 0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x1444004d, 0x42040,
+0xc4102b, 0x1040fff1, 0x0, 0x8f820200, 0x451025, 0xaf820200,
+0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820220, 0x3c030004, 0x431024, 0x1440000f, 0x0, 0x8f820220,
+0x3c03ffff, 0x34637fff, 0x431024, 0xaf820220, 0x8f830054, 0x8f820054,
+0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
+0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1440000d, 0x0,
+0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0,
+0x8f820220, 0x3c030004, 0x431024, 0x1040001b, 0x1021, 0x8f830220,
+0x24020001, 0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700, 0x441025,
+0xaf820220, 0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, 0x8f820220,
+0x3c030300, 0x431024, 0x14400003, 0x0, 0x10000008, 0x1021,
+0x8f820220, 0x34420002, 0xaf820220, 0x8f830220, 0x24020001, 0x641825,
+0xaf830220, 0x3e00008, 0x0, 0x2021, 0x3c050100, 0x24020001,
+0xaf80021c, 0xaf820200, 0xaf820220, 0x27625000, 0xaf8200c0, 0x27625000,
+0xaf8200c4, 0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0, 0x27625000,
+0xaf8200d4, 0x27625000, 0xaf8200d8, 0x27623000, 0xaf8200e0, 0x27623000,
+0xaf8200e4, 0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0, 0x27622800,
+0xaf8200f4, 0x27622800, 0xaf8200f8, 0x418c0, 0x24840001, 0x3631021,
+0xac453004, 0x3631021, 0xac403000, 0x28820200, 0x1440fff9, 0x418c0,
+0x2021, 0x418c0, 0x24840001, 0x3631021, 0xac402804, 0x3631021,
+0xac402800, 0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c, 0x24030080,
+0x24040100, 0xac600000, 0x24630004, 0x64102b, 0x5440fffd, 0xac600000,
+0x8f830040, 0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 0x43102b,
+0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x10000008,
+0x0, 0x10620004, 0x24020800, 0x10000004, 0x0, 0x24020700,
+0x3c010001, 0xac223420, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0034,
+0xafb50030, 0xafb3002c, 0xafb10028, 0x3c010001, 0xc004459, 0xac203408,
+0x24040001, 0x2821, 0x27a60020, 0x34028000, 0xc004076, 0xa7a20020,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004034, 0x27a60020,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004034, 0x27a60020,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 0xc004034, 0x27a60018,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023,
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 0xc004034, 0x27a6001a,
+0x97a20020, 0x10400024, 0x24020001, 0x3c020001, 0x8c423408, 0x97a30018,
+0x34420001, 0x3c010001, 0xac223408, 0x24020015, 0x14620004, 0x3402f423,
+0x97a3001a, 0x10620018, 0x24020003, 0x97a30018, 0x24027810, 0x14620014,
+0x24020002, 0x97a3001a, 0x24020001, 0x14620010, 0x24020002, 0x1000000e,
+0x24020004, 0x3c020001, 0x8c423408, 0x34420008, 0x3c010001, 0xac223408,
+0x10000058, 0x24020004, 0x3c020001, 0x8c423408, 0x34420004, 0x3c010001,
+0x100000a8, 0xac223408, 0x3c010001, 0xac22353c, 0x24020e00, 0xaf820238,
+0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, 0xac23340c, 0x10000002,
+0x248401f4, 0x8f820054, 0x821023, 0x2c4201f5, 0x1440fffc, 0x3c0200c8,
+0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, 0x246301f4,
+0x8f820054, 0x621023, 0x2c4201f5, 0x1440fffc, 0x8821, 0x3c1300c8,
+0x367301f6, 0x2415fffd, 0xc003f77, 0x0, 0x8f830054, 0x8f820054,
0x10000002, 0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, 0x1440fffc,
-0x8821, 0x3c1300c8, 0x367301f6, 0x2415fffd, 0xc003f2b, 0x0,
-0x8f830054, 0x8f820054, 0x10000002, 0x246301f4, 0x8f820054, 0x621023,
-0x2c4201f5, 0x1440fffc, 0x0, 0xaf930238, 0x8f830054, 0x8f820054,
-0x10000002, 0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
-0x0, 0x8f820220, 0x34420002, 0xaf820220, 0x8f820200, 0x24040001,
-0x24057fff, 0x551024, 0xaf820200, 0xaf840204, 0x8f830054, 0x8f820054,
+0x0, 0xaf930238, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
+0x34420002, 0xaf820220, 0x8f820200, 0x24040001, 0x24057fff, 0x551024,
+0xaf820200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224,
+0x14440005, 0x34028000, 0x42040, 0xa4102b, 0x1040fff0, 0x34028000,
+0x1082ffa6, 0x26310001, 0x2e220014, 0x1440ffce, 0x24020004, 0x3c010001,
+0xac22340c, 0x8821, 0x3c13ffff, 0x36733f7f, 0xc003f77, 0x0,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x531024, 0x34425080,
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 0x8f820054,
+0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820044, 0x531024,
+0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a,
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002,
+0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x0,
+0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 0x8f830200, 0x24057fff,
+0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054,
0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
0x0, 0x8f820224, 0x14440005, 0x34028000, 0x42040, 0xa4102b,
-0x1040fff0, 0x34028000, 0x1082ffa6, 0x26310001, 0x2e220014, 0x1440ffce,
-0x24020004, 0x3c010001, 0xac2232ac, 0x8821, 0x3c13ffff, 0x36733f7f,
-0xc003f2b, 0x0, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
-0x531024, 0x34425080, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002,
-0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0,
-0x8f820044, 0x531024, 0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc,
-0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8f830054,
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065,
-0x1440fffc, 0x0, 0x8f820220, 0x24040001, 0x34420002, 0xaf820220,
-0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x14440005, 0x34028000,
-0x42040, 0xa4102b, 0x1040fff0, 0x34028000, 0x1082ff57, 0x26310001,
-0x2e220064, 0x1440ffb0, 0x0, 0x3c020001, 0x8c4232a8, 0x30420004,
-0x14400007, 0x3c08fff0, 0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024,
-0xaf820044, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001,
-0x8ce733dc, 0x3c040001, 0x24843080, 0x24020001, 0x3c010001, 0xac2232b0,
-0xafa60010, 0x3c060001, 0x8cc632a8, 0x97a2001a, 0x3c05000d, 0x34a50100,
-0x3c010001, 0xac2032ac, 0x681821, 0x3c010001, 0xac2333d4, 0xc0028eb,
-0xafa20014, 0x8fbf0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008,
-0x27bd0038, 0x27bdffe8, 0x24070004, 0x3c040001, 0x8c8432ac, 0x3021,
-0x24020001, 0x1482000a, 0xafbf0010, 0x3c020001, 0x8c4254bc, 0x3c050004,
-0x30428000, 0x1040000c, 0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240,
-0x3c020001, 0x8c4254bc, 0x3c05000f, 0x30428000, 0x10400003, 0x34a54240,
-0x3c05001e, 0x34a58480, 0x3c020001, 0x8c4233d4, 0x8f830054, 0x451021,
-0x431023, 0x45102b, 0x1440002e, 0x0, 0x3c020001, 0x8c4232b4,
-0x1440002a, 0x2cc20001, 0x7182b, 0x431024, 0x1040001d, 0x0,
-0x3c090001, 0x8d2932a8, 0x240b0001, 0x3c054000, 0x3c080001, 0x250854bc,
-0x250afffc, 0x42042, 0x14800002, 0x24e7ffff, 0x24040008, 0x891024,
-0x5040000b, 0x2cc20001, 0x148b0004, 0x0, 0x8d020000, 0x10000003,
-0x451024, 0x8d420000, 0x451024, 0x54400001, 0x24060001, 0x2cc20001,
-0x7182b, 0x431024, 0x5440ffed, 0x42042, 0x3c010001, 0x10c00020,
-0xac2432ac, 0x8f830054, 0x24020001, 0x3c010001, 0xac2232b0, 0x3c010001,
-0xac2333d4, 0x3c020001, 0x8c4232b0, 0x10400004, 0x24020001, 0x3c010001,
-0xac2032b0, 0xaee279c8, 0x8ee379c8, 0x24020008, 0x10620005, 0x24020001,
-0xc003dd7, 0x0, 0x1000000b, 0x0, 0x3c030001, 0x8c6332ac,
-0x10620007, 0x2402000e, 0x3c030001, 0x8c635430, 0x10620003, 0x0,
-0xc004430, 0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0,
-0x3c03fdff, 0x3c040001, 0x8c8432ac, 0x3c020001, 0x8c4232c4, 0x3463ffff,
-0x283a024, 0x14820006, 0xafbf0018, 0x8ee379c8, 0x3c020001, 0x8c4232c8,
-0x10620006, 0x0, 0x8ee279c8, 0x3c010001, 0xac2432c4, 0x3c010001,
-0xac2232c8, 0x3c030001, 0x8c6332ac, 0x24020002, 0x10620139, 0x2c620003,
-0x10400005, 0x24020001, 0x1062000a, 0x0, 0x10000131, 0x0,
-0x24020004, 0x10620070, 0x24020008, 0x106200ac, 0x24020001, 0x1000012a,
-0x0, 0x8ee279c8, 0x2443ffff, 0x2c620008, 0x10400127, 0x31080,
-0x3c010001, 0x220821, 0x8c223098, 0x400008, 0x0, 0xc003f2b,
-0x0, 0x3c020001, 0x8c4232b8, 0x3c010001, 0xac203240, 0x104000e8,
-0x24020002, 0xaee279c8, 0x3c010001, 0x10000116, 0xac2032b8, 0xc00406b,
-0x0, 0x3c030001, 0x8c6332d0, 0x24020011, 0x1462010f, 0x24020003,
-0x100000aa, 0x0, 0x3c050001, 0x8ca532ac, 0x3c060001, 0x8cc654bc,
-0xc004680, 0x24040001, 0x24020005, 0x3c010001, 0xac2032b8, 0x10000102,
-0xaee279c8, 0x3c040001, 0x2484308c, 0x3c05000f, 0x34a50100, 0x3021,
-0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x100000f7, 0x0,
-0x8f820220, 0x3c03f700, 0x431025, 0x100000ae, 0xaf820220, 0x8f820220,
-0x3c030004, 0x431024, 0x144000bc, 0x24020007, 0x8f830054, 0x3c020001,
-0x8c4233d0, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000e5, 0x24020001,
-0x100000e1, 0x0, 0x3c050001, 0x8ca532ac, 0xc004785, 0x24040001,
-0xc00484d, 0x24040001, 0x3c030001, 0x8c6354b4, 0x46100d7, 0x24020001,
-0x3c020008, 0x621024, 0x10400006, 0x0, 0x8f820214, 0x3c03ffff,
-0x431024, 0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024,
-0x3442241f, 0xaf820214, 0x8f820220, 0x3c030200, 0x283a025, 0x34420002,
-0xaf820220, 0x24020008, 0xc003b1e, 0xaee279c8, 0x100000c1, 0x0,
-0x8ee279c8, 0x2443ffff, 0x2c620008, 0x104000bc, 0x31080, 0x3c010001,
-0x220821, 0x8c2230b8, 0x400008, 0x0, 0xc003a65, 0x0,
-0x3c010001, 0xac2032b0, 0xaf800204, 0x3c010001, 0xc003f2b, 0xac205480,
-0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0x34425080, 0xaf820044,
-0x8f830054, 0x3c010001, 0xac203240, 0x10000062, 0x24020002, 0x3c020001,
-0x8c4254b8, 0x30424000, 0x10400004, 0x0, 0x8f820044, 0x10000006,
-0x3442f080, 0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080,
-0xaf820044, 0x8f830054, 0x10000051, 0x24020004, 0xc003b78, 0x0,
-0x1040008d, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c8433c8,
-0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x14800067, 0xaee279c8,
-0x1000006c, 0x0, 0x8ee279c8, 0x2443ffff, 0x2c620007, 0x1040007e,
-0x31080, 0x3c010001, 0x220821, 0x8c2230d8, 0x400008, 0x0,
-0xc003a65, 0x0, 0x3c010001, 0xac2032b0, 0xaf800204, 0x3c010001,
-0xc003f2b, 0xac205480, 0x8f830054, 0x3c010001, 0xac203240, 0x1000002a,
-0x24020002, 0x8f830054, 0x3c020001, 0x8c4233d0, 0x2463d8f0, 0x431023,
-0x2c422710, 0x14400064, 0x24020003, 0x10000062, 0xaee279c8, 0x3c020001,
-0x8c4254b8, 0x30424000, 0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6,
-0x344201fe, 0xaf820238, 0x8f830054, 0x10000014, 0x24020004, 0x8f830054,
-0x3c020001, 0x8c4233d0, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440004e,
-0x24020005, 0x1000004c, 0xaee279c8, 0x8f820220, 0x3c03f700, 0x431025,
-0xaf820220, 0xaf800204, 0x3c010001, 0xac205480, 0x8f830054, 0x24020006,
-0xaee279c8, 0x3c010001, 0x1000003f, 0xac2333d0, 0x3c05fffe, 0x34a57960,
-0x3c040001, 0x8f820054, 0x3c030001, 0x8c6333d0, 0x3484869f, 0x451021,
-0x621823, 0x83202b, 0x10800033, 0x0, 0x24020007, 0x10000030,
-0xaee279c8, 0xc003b78, 0x0, 0x1040002a, 0x24020001, 0x8f820214,
-0x3c03ffff, 0x3c040001, 0x8c8433c8, 0x431024, 0x3442251f, 0xaf820214,
-0x24020008, 0x1080000b, 0xaee279c8, 0x8f820220, 0x34420002, 0xaf820220,
-0x24020001, 0x3c010001, 0xac225430, 0xc004430, 0x8f840220, 0x10000018,
-0x0, 0x8f820220, 0x3c030008, 0x431024, 0x14400013, 0x3c020200,
-0x282a025, 0x2402000e, 0x3c010001, 0xac225430, 0xc00484d, 0x24040001,
-0x8f820220, 0x34420002, 0xc003b1e, 0xaf820220, 0x3c050001, 0x8ca532ac,
-0xc004785, 0x24040001, 0x10000003, 0x0, 0x3c010001, 0xac2232b0,
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220,
-0x34420004, 0xaf820220, 0x8f820200, 0x3c040001, 0x8c8432ac, 0x34420004,
-0xaf820200, 0x24020002, 0x1082003a, 0x2c820003, 0x10400005, 0x24020001,
-0x1082000a, 0x3c03f0ff, 0x100000a8, 0x0, 0x24020004, 0x10820055,
-0x24020008, 0x10820074, 0x3c02f0ff, 0x100000a1, 0x0, 0x8f820050,
-0x3463ffff, 0x3c05ffff, 0x34a53f7f, 0x431024, 0x3c030700, 0x431025,
-0xaf820050, 0x24020e00, 0xaf840200, 0xaf840220, 0xaf820238, 0x8f820044,
-0x3c030001, 0x8c633298, 0x3c040001, 0x8c8433dc, 0x451024, 0x34630022,
-0xaf820044, 0x24020004, 0x1082000c, 0xaf830200, 0x3c020001, 0x8c4232c0,
-0x3c030001, 0x8c6332a4, 0x3c040001, 0x8c84329c, 0x34428000, 0x621825,
-0x641825, 0x1000007e, 0x34620002, 0x3c020001, 0x8c4232a4, 0x3c030001,
-0x8c6332c0, 0x3c040001, 0x8c84329c, 0x431025, 0x441025, 0x10000074,
-0x34420002, 0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c8433c8,
-0x621824, 0x3c020d00, 0x621825, 0x24020001, 0xaf830050, 0xaf820200,
-0xaf820220, 0x24020e00, 0xaf820238, 0x10800005, 0x3c033f00, 0x3c020001,
-0x8c423290, 0x10000004, 0x34630070, 0x3c020001, 0x8c423290, 0x34630072,
-0x431025, 0xaf820200, 0x3c030001, 0x8c633294, 0x3c04f700, 0x3c020001,
-0x8c4232a4, 0x3c050001, 0x8ca532c0, 0x641825, 0x431025, 0x10000050,
-0x451025, 0x3c03f0ff, 0x8f820050, 0x3463ffff, 0x3c04ffff, 0x431024,
-0x3c030a00, 0x431025, 0xaf820050, 0x24020001, 0xaf820200, 0xaf820220,
-0x24020e01, 0xaf820238, 0x8f820044, 0x34843f7f, 0x3c030001, 0x8c6333c8,
-0x441024, 0x34420080, 0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001,
-0x8c423290, 0x10000004, 0x346300e0, 0x3c020001, 0x8c423290, 0x346300e2,
-0x431025, 0xaf820200, 0x10000025, 0x3c05f700, 0x8f830050, 0x3c040001,
-0x8c8433c8, 0x3442ffff, 0x621824, 0xaf830050, 0x10800013, 0x3c0500c8,
-0x34a501fb, 0x3c063f00, 0x3c030001, 0x8c6332a0, 0x3c040001, 0x8c843290,
-0x34c600e0, 0x24020001, 0xaf820200, 0xaf820220, 0xaf850238, 0x24630001,
-0x862025, 0x3c010001, 0xac2332a0, 0xaf840200, 0x1000000b, 0x3c05f700,
-0x3c0200c8, 0x344201fb, 0x3c030001, 0x8c633290, 0x3c043f00, 0x348400e2,
-0xaf820238, 0x641825, 0xaf830200, 0x3c05f700, 0x34a58000, 0x3c030001,
-0x8c633294, 0x3c020001, 0x8c4232a4, 0x3c040001, 0x8c8432c0, 0x651825,
-0x431025, 0x441025, 0xaf820220, 0x3e00008, 0x0, 0x0,
-0x27bdffd8, 0xafb50018, 0x80a821, 0xafbe001c, 0xa0f021, 0xafb30014,
-0xc09821, 0xafb10010, 0x8821, 0xafbf0020, 0xa6600000, 0xc0043e7,
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7,
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7,
-0x2021, 0x24110010, 0x2b11024, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fffa, 0x2b11024, 0x24110010, 0x3d11024,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa,
-0x3d11024, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7,
-0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000,
-0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x0, 0x8fbf0020,
-0x8fbe001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028,
-0x27bdffd8, 0xafb30014, 0x809821, 0xafb50018, 0xa0a821, 0xafbe001c,
-0xc0f021, 0xafb10010, 0x8821, 0xafbf0020, 0xc0043e7, 0x24040001,
-0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021,
-0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001,
-0x24110010, 0x2711024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7,
-0x118842, 0x1620fffa, 0x2711024, 0x24110010, 0x2b11024, 0x10400002,
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x2b11024,
-0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x97c20000,
-0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842,
-0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8fbf0020, 0x8fbe001c,
-0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x3c030001,
-0x8c6332d0, 0x3c020001, 0x8c423314, 0x27bdffd8, 0xafbf0020, 0xafb3001c,
-0x10620003, 0xafb10018, 0x3c010001, 0xac233314, 0x2463ffff, 0x2c620013,
-0x10400349, 0x31080, 0x3c010001, 0x220821, 0x8c223100, 0x400008,
-0x0, 0xc00440d, 0x8821, 0x34028000, 0xa7a20010, 0x27b30010,
-0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0,
-0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021,
-0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010,
-0xc0043e7, 0x2021, 0x118842, 0x1620fffc, 0x0, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8,
-0x0, 0xc00440d, 0x0, 0x1000030e, 0x24020002, 0x27b30010,
-0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020,
-0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001,
-0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, 0x32220001,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa,
-0x32220001, 0x24110010, 0xc0043e7, 0x2021, 0x118842, 0x1620fffc,
-0x0, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7,
-0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000,
-0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x0, 0x97a20010,
-0x30428000, 0x144002dc, 0x24020003, 0x100002d8, 0x0, 0x24021200,
-0xa7a20010, 0x27b30010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001,
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010,
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842,
-0x1620fffa, 0x32220001, 0x24110010, 0xc0043e7, 0x2021, 0x118842,
-0x1620fffc, 0x0, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021,
-0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0,
-0x8f830054, 0x10000296, 0x24020004, 0x8f830054, 0x3c020001, 0x8c4233d8,
-0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, 0x3c030001,
-0x8c6333dc, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003,
-0x10620005, 0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 0x24020011,
-0x1000028d, 0x24020005, 0x24020014, 0xa7a20010, 0x27b30010, 0x8821,
-0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0,
-0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021,
-0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010,
-0x32220012, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842,
-0x1620fffa, 0x32220012, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021,
-0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0,
-0x8f830054, 0x10000248, 0x24020006, 0x8f830054, 0x3c020001, 0x8c4233d8,
-0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, 0x24020007, 0x1000024c,
-0x0, 0x24020006, 0xa7a20010, 0x27b30010, 0x8821, 0xc0043e7,
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7,
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7,
+0x1040fff0, 0x34028000, 0x1082ff57, 0x26310001, 0x2e220064, 0x1440ffb0,
+0x0, 0x3c020001, 0x8c423408, 0x30420004, 0x14400007, 0x3c08fff0,
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, 0x3c08fff0,
+0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, 0x8ce7353c, 0x3c040001,
+0x248431e0, 0x24020001, 0x3c010001, 0xac223410, 0xafa60010, 0x3c060001,
+0x8cc63408, 0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001, 0xac20340c,
+0x681821, 0x3c010001, 0xac233534, 0xc00290f, 0xafa20014, 0x8fbf0034,
+0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0038, 0x27bdffe8,
+0x24070004, 0x3c040001, 0x8c84340c, 0x3021, 0x24020001, 0x1482000a,
+0xafbf0010, 0x3c020001, 0x8c42561c, 0x3c050004, 0x30428000, 0x1040000c,
+0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240, 0x3c020001, 0x8c42561c,
+0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480,
+0x3c020001, 0x8c423534, 0x8f830054, 0x451021, 0x431023, 0x45102b,
+0x1440002e, 0x0, 0x3c020001, 0x8c423414, 0x1440002a, 0x2cc20001,
+0x7182b, 0x431024, 0x1040001d, 0x0, 0x3c090001, 0x8d293408,
+0x240b0001, 0x3c054000, 0x3c080001, 0x2508561c, 0x250afffc, 0x42042,
+0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 0x2cc20001,
+0x148b0004, 0x0, 0x8d020000, 0x10000003, 0x451024, 0x8d420000,
+0x451024, 0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 0x431024,
+0x5440ffed, 0x42042, 0x3c010001, 0x10c00020, 0xac24340c, 0x8f830054,
+0x24020001, 0x3c010001, 0xac223410, 0x3c010001, 0xac233534, 0x3c020001,
+0x8c423410, 0x10400004, 0x24020001, 0x3c010001, 0xac203410, 0xaee279c8,
+0x8ee379c8, 0x24020008, 0x10620005, 0x24020001, 0xc003e23, 0x0,
+0x1000000b, 0x0, 0x3c030001, 0x8c63340c, 0x10620007, 0x2402000e,
+0x3c030001, 0x8c635590, 0x10620003, 0x0, 0xc00447c, 0x8f840220,
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c03fdff, 0x3c040001,
+0x8c84340c, 0x3c020001, 0x8c423424, 0x3463ffff, 0x283a024, 0x14820006,
+0xafbf0018, 0x8ee379c8, 0x3c020001, 0x8c423428, 0x10620006, 0x0,
+0x8ee279c8, 0x3c010001, 0xac243424, 0x3c010001, 0xac223428, 0x3c030001,
+0x8c63340c, 0x24020002, 0x10620139, 0x2c620003, 0x10400005, 0x24020001,
+0x1062000a, 0x0, 0x10000131, 0x0, 0x24020004, 0x10620070,
+0x24020008, 0x106200ac, 0x24020001, 0x1000012a, 0x0, 0x8ee279c8,
+0x2443ffff, 0x2c620008, 0x10400127, 0x31080, 0x3c010001, 0x220821,
+0x8c2231f8, 0x400008, 0x0, 0xc003f77, 0x0, 0x3c020001,
+0x8c423418, 0x3c010001, 0xac2033a0, 0x104000e8, 0x24020002, 0xaee279c8,
+0x3c010001, 0x10000116, 0xac203418, 0xc0040b7, 0x0, 0x3c030001,
+0x8c633430, 0x24020011, 0x1462010f, 0x24020003, 0x100000aa, 0x0,
+0x3c050001, 0x8ca5340c, 0x3c060001, 0x8cc6561c, 0xc0046cc, 0x24040001,
+0x24020005, 0x3c010001, 0xac203418, 0x10000102, 0xaee279c8, 0x3c040001,
+0x248431ec, 0x3c05000f, 0x34a50100, 0x3021, 0x3821, 0xafa00010,
+0xc00290f, 0xafa00014, 0x100000f7, 0x0, 0x8f820220, 0x3c03f700,
+0x431025, 0x100000ae, 0xaf820220, 0x8f820220, 0x3c030004, 0x431024,
+0x144000bc, 0x24020007, 0x8f830054, 0x3c020001, 0x8c423530, 0x2463d8f0,
+0x431023, 0x2c422710, 0x144000e5, 0x24020001, 0x100000e1, 0x0,
+0x3c050001, 0x8ca5340c, 0xc0047d1, 0x24040001, 0xc004899, 0x24040001,
+0x3c030001, 0x8c635614, 0x46100d7, 0x24020001, 0x3c020008, 0x621024,
+0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 0x431024, 0x10000005,
+0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, 0xaf820214,
+0x8f820220, 0x3c030200, 0x283a025, 0x34420002, 0xaf820220, 0x24020008,
+0xc003b6a, 0xaee279c8, 0x100000c1, 0x0, 0x8ee279c8, 0x2443ffff,
+0x2c620008, 0x104000bc, 0x31080, 0x3c010001, 0x220821, 0x8c223218,
+0x400008, 0x0, 0xc003ab1, 0x0, 0x3c010001, 0xac203410,
+0xaf800204, 0x3c010001, 0xc003f77, 0xac2055e0, 0x8f820044, 0x3c03ffff,
+0x34633f7f, 0x431024, 0x34425080, 0xaf820044, 0x8f830054, 0x3c010001,
+0xac2033a0, 0x10000062, 0x24020002, 0x3c020001, 0x8c425618, 0x30424000,
+0x10400004, 0x0, 0x8f820044, 0x10000006, 0x3442f080, 0x8f820044,
+0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, 0xaf820044, 0x8f830054,
+0x10000051, 0x24020004, 0xc003bc4, 0x0, 0x1040008d, 0x24020001,
+0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c843528, 0x431024, 0x3442251f,
+0xaf820214, 0x24020008, 0x14800067, 0xaee279c8, 0x1000006c, 0x0,
+0x8ee279c8, 0x2443ffff, 0x2c620007, 0x1040007e, 0x31080, 0x3c010001,
+0x220821, 0x8c223238, 0x400008, 0x0, 0xc003ab1, 0x0,
+0x3c010001, 0xac203410, 0xaf800204, 0x3c010001, 0xc003f77, 0xac2055e0,
+0x8f830054, 0x3c010001, 0xac2033a0, 0x1000002a, 0x24020002, 0x8f830054,
+0x3c020001, 0x8c423530, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400064,
+0x24020003, 0x10000062, 0xaee279c8, 0x3c020001, 0x8c425618, 0x30424000,
+0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, 0x344201fe, 0xaf820238,
+0x8f830054, 0x10000014, 0x24020004, 0x8f830054, 0x3c020001, 0x8c423530,
+0x2463d8f0, 0x431023, 0x2c422710, 0x1440004e, 0x24020005, 0x1000004c,
+0xaee279c8, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0xaf800204,
+0x3c010001, 0xac2055e0, 0x8f830054, 0x24020006, 0xaee279c8, 0x3c010001,
+0x1000003f, 0xac233530, 0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054,
+0x3c030001, 0x8c633530, 0x3484869f, 0x451021, 0x621823, 0x83202b,
+0x10800033, 0x0, 0x24020007, 0x10000030, 0xaee279c8, 0xc003bc4,
+0x0, 0x1040002a, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001,
+0x8c843528, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x1080000b,
+0xaee279c8, 0x8f820220, 0x34420002, 0xaf820220, 0x24020001, 0x3c010001,
+0xac225590, 0xc00447c, 0x8f840220, 0x10000018, 0x0, 0x8f820220,
+0x3c030008, 0x431024, 0x14400013, 0x3c020200, 0x282a025, 0x2402000e,
+0x3c010001, 0xac225590, 0xc004899, 0x24040001, 0x8f820220, 0x34420002,
+0xc003b6a, 0xaf820220, 0x3c050001, 0x8ca5340c, 0xc0047d1, 0x24040001,
+0x10000003, 0x0, 0x3c010001, 0xac223410, 0x8fbf0018, 0x3e00008,
+0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 0xaf820220,
+0x8f820200, 0x3c040001, 0x8c84340c, 0x34420004, 0xaf820200, 0x24020002,
+0x1082003a, 0x2c820003, 0x10400005, 0x24020001, 0x1082000a, 0x3c03f0ff,
+0x100000a8, 0x0, 0x24020004, 0x10820055, 0x24020008, 0x10820074,
+0x3c02f0ff, 0x100000a1, 0x0, 0x8f820050, 0x3463ffff, 0x3c05ffff,
+0x34a53f7f, 0x431024, 0x3c030700, 0x431025, 0xaf820050, 0x24020e00,
+0xaf840200, 0xaf840220, 0xaf820238, 0x8f820044, 0x3c030001, 0x8c6333f8,
+0x3c040001, 0x8c84353c, 0x451024, 0x34630022, 0xaf820044, 0x24020004,
+0x1082000c, 0xaf830200, 0x3c020001, 0x8c423420, 0x3c030001, 0x8c633404,
+0x3c040001, 0x8c8433fc, 0x34428000, 0x621825, 0x641825, 0x1000007e,
+0x34620002, 0x3c020001, 0x8c423404, 0x3c030001, 0x8c633420, 0x3c040001,
+0x8c8433fc, 0x431025, 0x441025, 0x10000074, 0x34420002, 0x8f830050,
+0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c843528, 0x621824, 0x3c020d00,
+0x621825, 0x24020001, 0xaf830050, 0xaf820200, 0xaf820220, 0x24020e00,
+0xaf820238, 0x10800005, 0x3c033f00, 0x3c020001, 0x8c4233f0, 0x10000004,
+0x34630070, 0x3c020001, 0x8c4233f0, 0x34630072, 0x431025, 0xaf820200,
+0x3c030001, 0x8c6333f4, 0x3c04f700, 0x3c020001, 0x8c423404, 0x3c050001,
+0x8ca53420, 0x641825, 0x431025, 0x10000050, 0x451025, 0x3c03f0ff,
+0x8f820050, 0x3463ffff, 0x3c04ffff, 0x431024, 0x3c030a00, 0x431025,
+0xaf820050, 0x24020001, 0xaf820200, 0xaf820220, 0x24020e01, 0xaf820238,
+0x8f820044, 0x34843f7f, 0x3c030001, 0x8c633528, 0x441024, 0x34420080,
+0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 0x8c4233f0, 0x10000004,
+0x346300e0, 0x3c020001, 0x8c4233f0, 0x346300e2, 0x431025, 0xaf820200,
+0x10000025, 0x3c05f700, 0x8f830050, 0x3c040001, 0x8c843528, 0x3442ffff,
+0x621824, 0xaf830050, 0x10800013, 0x3c0500c8, 0x34a501fb, 0x3c063f00,
+0x3c030001, 0x8c633400, 0x3c040001, 0x8c8433f0, 0x34c600e0, 0x24020001,
+0xaf820200, 0xaf820220, 0xaf850238, 0x24630001, 0x862025, 0x3c010001,
+0xac233400, 0xaf840200, 0x1000000b, 0x3c05f700, 0x3c0200c8, 0x344201fb,
+0x3c030001, 0x8c6333f0, 0x3c043f00, 0x348400e2, 0xaf820238, 0x641825,
+0xaf830200, 0x3c05f700, 0x34a58000, 0x3c030001, 0x8c6333f4, 0x3c020001,
+0x8c423404, 0x3c040001, 0x8c843420, 0x651825, 0x431025, 0x441025,
+0xaf820220, 0x3e00008, 0x0, 0x0, 0x27bdffd8, 0xafb50018,
+0x80a821, 0xafbe001c, 0xa0f021, 0xafb30014, 0xc09821, 0xafb10010,
+0x8821, 0xafbf0020, 0xa6600000, 0xc004433, 0x24040001, 0x26310001,
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433,
+0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010,
+0x2b11024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fffa, 0x2b11024, 0x24110010, 0x3d11024, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x3d11024, 0xc004459,
+0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005,
+0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7,
+0x0, 0xc004459, 0x0, 0x8fbf0020, 0x8fbe001c, 0x8fb50018,
+0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb30014,
+0x809821, 0xafb50018, 0xa0a821, 0xafbe001c, 0xc0f021, 0xafb10010,
+0x8821, 0xafbf0020, 0xc004433, 0x24040001, 0x26310001, 0x2e220020,
+0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001,
+0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 0x2711024,
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa,
+0x2711024, 0x24110010, 0x2b11024, 0x10400002, 0x2021, 0x24040001,
+0xc004433, 0x118842, 0x1620fffa, 0x2b11024, 0xc004433, 0x24040001,
+0xc004433, 0x2021, 0x34118000, 0x97c20000, 0x511024, 0x10400002,
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0,
+0xc004459, 0x0, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 0x8fb30014,
+0x8fb10010, 0x3e00008, 0x27bd0028, 0x3c030001, 0x8c633430, 0x3c020001,
+0x8c423474, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 0x10620003, 0xafb10018,
+0x3c010001, 0xac233474, 0x2463ffff, 0x2c620013, 0x10400349, 0x31080,
+0x3c010001, 0x220821, 0x8c223260, 0x400008, 0x0, 0xc004459,
+0x8821, 0x34028000, 0xa7a20010, 0x27b30010, 0xc004433, 0x24040001,
+0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021,
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001,
+0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0xc004433, 0x2021,
+0x118842, 0x1620fffc, 0x0, 0xc004433, 0x24040001, 0xc004433,
+0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459,
+0x0, 0x1000030e, 0x24020002, 0x27b30010, 0xa7a00010, 0x8821,
+0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0,
+0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 0x24040001,
+0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010,
+0xc004433, 0x2021, 0x118842, 0x1620fffc, 0x0, 0xc004459,
+0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005,
+0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7,
+0x0, 0xc004459, 0x0, 0x97a20010, 0x30428000, 0x144002dc,
+0x24020003, 0x100002d8, 0x0, 0x24021200, 0xa7a20010, 0x27b30010,
+0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433,
+0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002,
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001,
+0x24110010, 0xc004433, 0x2021, 0x118842, 0x1620fffc, 0x0,
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000,
+0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 0x10000296,
+0x24020004, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023,
+0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 0x8c63353c, 0x10620297,
+0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004,
+0x10620291, 0x2402000f, 0x1000028f, 0x24020011, 0x1000028d, 0x24020005,
+0x24020014, 0xa7a20010, 0x27b30010, 0x8821, 0xc004433, 0x24040001,
+0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021,
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001,
+0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220012, 0x10400002,
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220012,
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000,
+0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 0x10000248,
+0x24020006, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400250, 0x24020007, 0x1000024c, 0x0, 0x24020006,
+0xa7a20010, 0x27b30010, 0x8821, 0xc004433, 0x24040001, 0x26310001,
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433,
+0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010,
+0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fffa, 0x32220001, 0x24110010, 0x32220013, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220013, 0xc004433,
+0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024,
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8,
+0x0, 0xc004459, 0x0, 0x8f830054, 0x10000207, 0x24020008,
+0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064,
+0x1440020f, 0x24020009, 0x1000020b, 0x0, 0x27b30010, 0xa7a00010,
+0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433,
+0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002,
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001,
+0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fffa, 0x32220018, 0xc004459, 0x34118000, 0xc004459,
+0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000,
+0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc004459,
+0x8821, 0x97a20010, 0x27b30010, 0x34420001, 0xa7a20010, 0xc004433,
+0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433,
+0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433,
0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220013,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa,
-0x32220013, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000,
-0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7,
-0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8f830054,
-0x10000207, 0x24020008, 0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c,
-0x431023, 0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 0x0,
-0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001,
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010,
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842,
-0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220018, 0xc00440d,
-0x34118000, 0xc00440d, 0x0, 0xc0043c7, 0x0, 0x50400005,
+0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220018,
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa,
+0x32220018, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000,
+0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054,
+0x10000193, 0x2402000a, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c,
+0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 0x0,
+0x27b30010, 0xa7a00010, 0x8821, 0xc004433, 0x24040001, 0x26310001,
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433,
+0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010,
+0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220017, 0xc004459,
+0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005,
0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7,
-0x0, 0xc00440d, 0x8821, 0x97a20010, 0x27b30010, 0x34420001,
-0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
-0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7,
-0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002,
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001,
-0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc0043e7,
-0x118842, 0x1620fffa, 0x32220018, 0xc0043e7, 0x24040001, 0xc0043e7,
+0x0, 0xc004459, 0x8821, 0x97a20010, 0x27b30010, 0x34420700,
+0xa7a20010, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433,
+0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002,
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001,
+0x24110010, 0x32220017, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fffa, 0x32220017, 0xc004433, 0x24040001, 0xc004433,
0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d,
-0x0, 0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, 0x3c020001,
-0x8c4233d8, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440019b, 0x2402000b,
-0x10000197, 0x0, 0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7,
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7,
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7,
+0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459,
+0x0, 0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, 0x3c020001,
+0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012,
+0x10000123, 0x0, 0x27b30010, 0xa7a00010, 0x8821, 0xc004433,
+0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433,
+0x2021, 0xc004433, 0x24040001, 0xc004433, 0x24040001, 0xc004433,
0x2021, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220017,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa,
-0x32220017, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7,
+0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220014,
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa,
+0x32220014, 0xc004459, 0x34118000, 0xc004459, 0x0, 0xc004413,
0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000,
-0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x8821, 0x97a20010,
-0x27b30010, 0x34420700, 0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001,
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010,
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842,
-0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220017, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8,
-0x0, 0xc00440d, 0x0, 0x8f830054, 0x1000011f, 0x2402000c,
-0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, 0x431023, 0x2c420064,
-0x14400127, 0x24020012, 0x10000123, 0x0, 0x27b30010, 0xa7a00010,
-0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
-0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x2021, 0x24110010, 0x32220001, 0x10400002,
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001,
-0x24110010, 0x32220014, 0x10400002, 0x2021, 0x24040001, 0xc0043e7,
-0x118842, 0x1620fffa, 0x32220014, 0xc00440d, 0x34118000, 0xc00440d,
-0x0, 0xc0043c7, 0x0, 0x50400005, 0x118842, 0x96620000,
-0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc00440d,
-0x8821, 0x97a20010, 0x27b30010, 0x34420010, 0xa7a20010, 0xc0043e7,
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7,
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7,
+0x118842, 0x1620fff7, 0x0, 0xc004459, 0x8821, 0x97a20010,
+0x27b30010, 0x34420010, 0xa7a20010, 0xc004433, 0x24040001, 0x26310001,
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433,
+0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010,
+0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fffa, 0x32220001, 0x24110010, 0x32220014, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220014, 0xc004433,
+0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024,
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8,
+0x0, 0xc004459, 0x0, 0x8f830054, 0x100000ab, 0x24020013,
+0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064,
+0x144000b3, 0x2402000d, 0x100000af, 0x0, 0x27b30010, 0xa7a00010,
+0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433,
+0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002,
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001,
+0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fffa, 0x32220018, 0xc004459, 0x34118000, 0xc004459,
+0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000,
+0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc004459,
+0x8821, 0x97a20010, 0x27b30010, 0x3042fffe, 0xa7a20010, 0xc004433,
+0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433,
+0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433,
0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220014,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa,
-0x32220014, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000,
-0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7,
-0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8f830054,
-0x100000ab, 0x24020013, 0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c,
-0x431023, 0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 0x0,
-0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001,
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7,
-0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010,
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842,
-0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220018, 0xc00440d,
-0x34118000, 0xc00440d, 0x0, 0xc0043c7, 0x0, 0x50400005,
-0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7,
-0x0, 0xc00440d, 0x8821, 0x97a20010, 0x27b30010, 0x3042fffe,
-0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb,
-0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7,
-0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002,
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001,
-0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc0043e7,
-0x118842, 0x1620fffa, 0x32220018, 0xc0043e7, 0x24040001, 0xc0043e7,
-0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021,
-0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d,
-0x0, 0x8f830054, 0x10000037, 0x2402000e, 0x24020840, 0xa7a20010,
-0x27b30010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020,
-0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001,
-0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001,
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa,
-0x32220001, 0x24110010, 0x32220013, 0x10400002, 0x2021, 0x24040001,
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220013, 0xc0043e7, 0x24040001,
-0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002,
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0,
-0xc00440d, 0x0, 0x8f830054, 0x24020010, 0x3c010001, 0xac2232d0,
-0x3c010001, 0x1000000c, 0xac2333d8, 0x8f830054, 0x3c020001, 0x8c4233d8,
-0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011,
-0x3c010001, 0xac2232d0, 0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008,
-0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, 0x431025, 0x3c030008,
-0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, 0x10000002, 0x24840001,
-0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff,
-0x42480, 0x621824, 0x3c020002, 0x822025, 0x641825, 0xaf830044,
-0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054,
-0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044,
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023,
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x8f820044,
-0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, 0x8f820044, 0x3c030001,
+0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220018,
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa,
+0x32220018, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000,
+0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433,
+0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054,
+0x10000037, 0x2402000e, 0x24020840, 0xa7a20010, 0x27b30010, 0x8821,
+0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0,
+0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021,
+0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021,
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010,
+0x32220013, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842,
+0x1620fffa, 0x32220013, 0xc004433, 0x24040001, 0xc004433, 0x2021,
+0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001,
+0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0,
+0x8f830054, 0x24020010, 0x3c010001, 0xac223430, 0x3c010001, 0x1000000c,
+0xac233538, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023,
+0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, 0xac223430,
+0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, 0x27bd0028, 0x8f850044,
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, 0x8f840054,
+0x8f820054, 0xa32824, 0x10000002, 0x24840001, 0x8f820054, 0x821023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
+0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824,
+0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c030001,
0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044,
0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054,
0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc,
-0x0, 0x3e00008, 0x0, 0x0, 0x27bdffe8, 0xafbf0010,
-0x8ee379c8, 0x24020008, 0x146201ca, 0x0, 0x3c020001, 0x8c4233c8,
-0x14400005, 0x0, 0xc003a65, 0x8f840224, 0x100001c2, 0x0,
-0x8f820220, 0x3c030008, 0x431024, 0x10400026, 0x24020001, 0x8f840224,
-0x8f820220, 0x3c030400, 0x431024, 0x10400006, 0x0, 0x3c010001,
-0xac205440, 0x3c010001, 0x1000000b, 0xac205460, 0x3c030001, 0x24635440,
-0x8c620000, 0x24420001, 0xac620000, 0x2c420002, 0x14400003, 0x24020001,
-0x3c010001, 0xac225460, 0x3c020001, 0x8c425460, 0x10400006, 0x30820040,
-0x10400004, 0x24020001, 0x3c010001, 0x10000003, 0xac225464, 0x3c010001,
-0xac205464, 0x3c010001, 0xac24543c, 0x3c010001, 0x1000000b, 0xac205470,
-0x3c010001, 0xac225470, 0x3c010001, 0xac205460, 0x3c010001, 0xac205440,
-0x3c010001, 0xac205464, 0x3c010001, 0xac20543c, 0x3c030001, 0x8c635430,
-0x3c020001, 0x8c425434, 0x50620004, 0x2463ffff, 0x3c010001, 0xac235434,
-0x2463ffff, 0x2c62000e, 0x1040017e, 0x31080, 0x3c010001, 0x220821,
-0x8c223150, 0x400008, 0x0, 0x3c02fdff, 0x3442ffff, 0x282a024,
-0x24020002, 0x3c010001, 0xac205460, 0x3c010001, 0xac205440, 0x3c010001,
-0xac205470, 0x3c010001, 0xac20543c, 0x3c010001, 0xac205464, 0x3c010001,
-0xac205458, 0x3c010001, 0xac205450, 0xaf800224, 0x3c010001, 0xac225430,
-0xc003a65, 0x0, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024,
-0xaf820200, 0x3c010001, 0xac205480, 0x8f830054, 0x3c020001, 0x8c425458,
-0x24040001, 0x3c010001, 0xac24546c, 0x24420001, 0x3c010001, 0xac225458,
-0x2c420004, 0x3c010001, 0xac235454, 0x14400006, 0x24020003, 0x3c010001,
-0xac2432b0, 0x3c010001, 0x10000148, 0xac205458, 0x3c010001, 0x10000145,
-0xac225430, 0x8f830054, 0x3c020001, 0x8c425454, 0x2463d8f0, 0x431023,
-0x2c422710, 0x1440013d, 0x24020004, 0x3c010001, 0x1000013a, 0xac225430,
-0x3c040001, 0x8c8433cc, 0x3c010001, 0xc004602, 0xac205448, 0x3c020001,
-0x8c42547c, 0xaf820204, 0x8f820204, 0x30420030, 0x14400125, 0x24020002,
-0x3c030001, 0x8c63547c, 0x24020005, 0x3c010001, 0xac225430, 0x3c010001,
-0x10000126, 0xac235480, 0x3c020001, 0x8c425460, 0x10400122, 0x0,
-0x3c020001, 0x8c42543c, 0x1040011e, 0x0, 0x3c010001, 0xac225468,
-0x24020003, 0x3c010001, 0xac225440, 0x100000c1, 0x24020006, 0x3c010001,
-0xac205448, 0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c425480,
-0x24030007, 0x3c010001, 0xac235430, 0x34420040, 0x3c010001, 0xac225480,
-0x3c020001, 0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c,
-0x104000f9, 0x24020002, 0x3c050001, 0x24a55440, 0x8ca20000, 0x2c424e21,
-0x104000f3, 0x24020002, 0x3c020001, 0x8c425464, 0x104000f8, 0x2404ffbf,
-0x3c020001, 0x8c42543c, 0x3c030001, 0x8c635468, 0x441024, 0x641824,
-0x14430007, 0x24020001, 0x24020003, 0xaca20000, 0x24020008, 0x3c010001,
-0x100000ea, 0xac225430, 0x3c010001, 0x100000e7, 0xac225430, 0x3c020001,
-0x8c42546c, 0x1040000c, 0x24020001, 0x3c040001, 0xc00460f, 0x8c84543c,
-0x3c020001, 0x8c425488, 0x14400005, 0x24020001, 0x3c020001, 0x8c425484,
-0x10400006, 0x24020001, 0x3c010001, 0xac2232b0, 0x3c010001, 0x100000d3,
-0xac205458, 0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c425480,
-0x3c030001, 0x8c635450, 0x34420040, 0x3c010001, 0xac225480, 0x3c020001,
-0x8c42543c, 0x2c630001, 0x318c0, 0x3c010001, 0xac235450, 0x30420008,
-0x3c010001, 0xac22544c, 0x8f830054, 0x24020009, 0x3c010001, 0xac225430,
-0x3c010001, 0x100000b9, 0xac235454, 0x8f830054, 0x3c020001, 0x8c425454,
-0x2463d8f0, 0x431023, 0x2c422710, 0x1440009f, 0x0, 0x3c020001,
-0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, 0x104000a0,
-0x24020002, 0x3c030001, 0x24635440, 0x8c620000, 0x2c424e21, 0x1040009a,
-0x24020002, 0x3c020001, 0x8c42546c, 0x1040000e, 0x0, 0x3c020001,
-0x8c42543c, 0x3c010001, 0xac20546c, 0x30420080, 0x1040002f, 0x2402000c,
-0x8f820204, 0x30420080, 0x1440000c, 0x24020003, 0x10000029, 0x2402000c,
-0x3c020001, 0x8c42543c, 0x30420080, 0x14400005, 0x24020003, 0x8f820204,
-0x30420080, 0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001,
-0xac225430, 0x3c040001, 0x24845478, 0x8c820000, 0x3c030001, 0x8c635450,
-0x431025, 0xaf820204, 0x8c830000, 0x3c040001, 0x8c845450, 0x2402000b,
-0x3c010001, 0xac225430, 0x641825, 0x3c010001, 0xac235480, 0x3c050001,
-0x24a55440, 0x8ca20000, 0x2c424e21, 0x10400066, 0x24020002, 0x3c020001,
-0x8c425470, 0x10400005, 0x0, 0x2402000c, 0x3c010001, 0x10000067,
-0xac225430, 0x3c020001, 0x8c425460, 0x10400063, 0x0, 0x3c040001,
-0x8c84543c, 0x10800055, 0x30820008, 0x3c030001, 0x8c63544c, 0x1062005b,
-0x24020003, 0x3c010001, 0xac245468, 0xaca20000, 0x24020006, 0x3c010001,
-0x10000054, 0xac225430, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054,
-0x2402000d, 0x3c010001, 0xac225430, 0x3c010001, 0xac235454, 0x8f830054,
-0x3c020001, 0x8c425454, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400031,
-0x0, 0x3c020001, 0x8c425470, 0x10400020, 0x2402000e, 0x3c030001,
-0x8c635484, 0x3c010001, 0x14600015, 0xac225430, 0xc003b1e, 0x0,
-0x3c050001, 0x8ca532ac, 0xc004785, 0x24040001, 0x3c030001, 0x8c6332ac,
-0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 0x8c4232a8, 0x10000003,
-0x2403fff7, 0x3c020001, 0x8c4232a8, 0x431024, 0x3c010001, 0xac2232a8,
-0x8f830224, 0x3c020200, 0x3c010001, 0xac23548c, 0x10000020, 0x282a025,
-0x3c020001, 0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c,
-0x1040000f, 0x24020002, 0x3c020001, 0x8c425440, 0x2c424e21, 0x1040000a,
-0x24020002, 0x3c020001, 0x8c425460, 0x1040000f, 0x0, 0x3c020001,
-0x8c42543c, 0x1440000b, 0x0, 0x24020002, 0x3c010001, 0x10000007,
-0xac225430, 0x3c020001, 0x8c425460, 0x10400003, 0x0, 0xc003a65,
-0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010,
-0x3e00008, 0x27bd0018, 0x3c030001, 0x24635488, 0x8c620000, 0x10400005,
-0x34422000, 0x3c010001, 0xac22547c, 0x10000003, 0xac600000, 0x3c010001,
-0xac24547c, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, 0xafbf0018,
-0x3c010001, 0xac225484, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024,
-0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02,
-0x30820001, 0x21200, 0x3c040001, 0x8c8433cc, 0x621825, 0x331c2,
-0x3c030001, 0x2463332c, 0x30828000, 0x21202, 0x30840001, 0x42200,
-0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000,
-0x24020001, 0x10620025, 0x0, 0x10600007, 0x24020002, 0x10620013,
-0x24020003, 0x1062002c, 0x3c05000f, 0x10000037, 0x0, 0x8f820200,
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff,
-0x431024, 0xaf820220, 0x3c010001, 0xac2054c4, 0x3c010001, 0x10000034,
-0xac2054cc, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe,
-0x3463ffff, 0x431024, 0xaf820220, 0x24020100, 0x3c010001, 0xac2254c4,
-0x3c010001, 0x10000026, 0xac2054cc, 0x8f820200, 0x2403feff, 0x431024,
-0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x3c010001,
-0xac2054c4, 0x3c010001, 0x10000019, 0xac2354cc, 0x8f820200, 0x34420100,
-0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x24020100,
-0x3c010001, 0xac2254c4, 0x3c010001, 0x1000000c, 0xac2354cc, 0x34a5ffff,
-0x3c040001, 0x24843188, 0xafa30010, 0xc0028eb, 0xafa00014, 0x10000004,
-0x0, 0x24020030, 0x3c010001, 0xac225488, 0x8fbf0018, 0x3e00008,
-0x27bd0020, 0x0, 0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c,
-0xa0f021, 0xafb10020, 0xc08821, 0x3c040001, 0x248431a0, 0x3c050009,
-0x3c020001, 0x8c4232ac, 0x34a59001, 0x2603021, 0x3c03821, 0xafbf0030,
-0xafb50028, 0xa7a0001a, 0xafb10014, 0xc0028eb, 0xafa20010, 0x24020002,
-0x13c200e7, 0x2fc20003, 0x10400005, 0x24020001, 0x13c2000a, 0x3c02fffb,
-0x100000e1, 0x0, 0x24020004, 0x13c2006d, 0x24020008, 0x13c2006c,
-0x3c02ffec, 0x100000da, 0x0, 0x3442ffff, 0x2228824, 0x13a940,
-0x3c010001, 0x350821, 0xac31549c, 0x3c024000, 0x2221024, 0x10400046,
-0x1123c2, 0x30840030, 0x111382, 0x3042000c, 0x3c030001, 0x246332d4,
-0x431021, 0x823821, 0x3c020020, 0x2221024, 0x10400006, 0x24020100,
-0x3c010001, 0x350821, 0xac2254a0, 0x10000005, 0x3c020080, 0x3c010001,
-0x350821, 0xac2054a0, 0x3c020080, 0x2221024, 0x10400006, 0x131940,
-0x3c020001, 0x3c010001, 0x230821, 0x10000005, 0xac2254a8, 0x131140,
-0x3c010001, 0x220821, 0xac2054a8, 0x94e30000, 0x32224000, 0x10400003,
-0xa7a30018, 0x34624000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004,
-0x24e60002, 0x34420001, 0xc00402a, 0xa4e20002, 0x24040001, 0x2821,
-0xc00402a, 0x27a60018, 0x3c020001, 0x8c4232ac, 0x24130001, 0x3c010001,
-0xac3332b8, 0x145e0004, 0x32228000, 0xc003a65, 0x0, 0x32228000,
-0x10400093, 0x0, 0xc003a65, 0x0, 0x24020002, 0x3c010001,
-0xac3332b0, 0x3c010001, 0x1000008b, 0xac2232ac, 0x24040001, 0x24050004,
-0x27b1001a, 0xc00402a, 0x2203021, 0x24040001, 0x2821, 0xc00402a,
-0x2203021, 0x3c020001, 0x551021, 0x8c425494, 0x3c040001, 0x8c8432ac,
-0x3c03bfff, 0x3463ffff, 0x3c010001, 0xac3e32b8, 0x431024, 0x3c010001,
-0x350821, 0x109e0072, 0xac225494, 0x10000072, 0x0, 0x3c02ffec,
-0x3442ffff, 0x2228824, 0x3c020008, 0x2228825, 0x131140, 0x3c010001,
-0x220821, 0xac315498, 0x3c022000, 0x2221024, 0x10400005, 0x24020001,
-0x3c010001, 0xac2233c8, 0x10000004, 0x3c024000, 0x3c010001, 0xac2033c8,
-0x3c024000, 0x2221024, 0x1440001a, 0x0, 0x3c020001, 0x8c4233c8,
-0x10400005, 0x24022020, 0x3c010001, 0xac2233cc, 0x24020001, 0xaee279c8,
-0x3c04bfff, 0x131940, 0x3c020001, 0x431021, 0x8c425490, 0x3c050001,
-0x8ca532ac, 0x3484ffff, 0x441024, 0x3c010001, 0x230821, 0xac225490,
-0x24020001, 0x10a20044, 0x0, 0x10000040, 0x0, 0x3c020001,
-0x8c4233c8, 0x1040001c, 0x24022000, 0x3c010001, 0xac2233cc, 0x3c0300a0,
-0x2231024, 0x14430005, 0x131140, 0x3402a000, 0x3c010001, 0x1000002d,
-0xac2233cc, 0x3c030001, 0x621821, 0x8c635498, 0x3c020020, 0x621024,
-0x10400004, 0x24022001, 0x3c010001, 0x10000023, 0xac2233cc, 0x3c020080,
-0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, 0xac2233cc,
-0x3c020020, 0x2221024, 0x10400007, 0x131940, 0x24020100, 0x3c010001,
-0x230821, 0xac2254a4, 0x10000006, 0x3c020080, 0x131140, 0x3c010001,
-0x220821, 0xac2054a4, 0x3c020080, 0x2221024, 0x10400006, 0x131940,
-0x3c020001, 0x3c010001, 0x230821, 0x10000005, 0xac2254ac, 0x131140,
-0x3c010001, 0x220821, 0xac2054ac, 0x3c030001, 0x8c6332ac, 0x24020001,
-0x10620003, 0x0, 0xc003a65, 0x0, 0x8fbf0030, 0x8fbe002c,
-0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffc8,
-0xafb50028, 0xa821, 0xafbe002c, 0xf021, 0xafb30024, 0x9821,
-0x24020002, 0xafbf0030, 0xafb10020, 0xafa4001c, 0xa7a00012, 0x10a2006a,
-0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 0x3c024000,
-0x100000ad, 0x2601021, 0x24020004, 0x10a20060, 0x24020008, 0x10a2005e,
-0x2601021, 0x100000a6, 0x0, 0x8fa7001c, 0x78940, 0x3c030001,
-0x711821, 0x8c63549c, 0x621024, 0x14400009, 0x24040001, 0x3c027fff,
-0x3442ffff, 0x629824, 0x3c010001, 0x310821, 0xac335494, 0x10000096,
-0x2601021, 0x24050001, 0xc003fe8, 0x27a60010, 0x24040001, 0x24050001,
-0xc003fe8, 0x27a60010, 0x97a20010, 0x30420004, 0x10400034, 0x3c134000,
-0x3c030001, 0x8c6333dc, 0x24020003, 0x10620008, 0x2c620004, 0x14400029,
-0x3c028000, 0x24020004, 0x10620014, 0x24040001, 0x10000024, 0x3c028000,
-0x24040001, 0x24050011, 0x27b10012, 0xc003fe8, 0x2203021, 0x24040001,
-0x24050011, 0xc003fe8, 0x2203021, 0x97a30012, 0x30624000, 0x10400002,
-0x3c1e0010, 0x3c1e0008, 0x3c150001, 0x10000010, 0x30628000, 0x24050014,
-0x27b10012, 0xc003fe8, 0x2203021, 0x24040001, 0x24050014, 0xc003fe8,
-0x2203021, 0x97a30012, 0x30621000, 0x10400002, 0x3c1e0010, 0x3c1e0008,
-0x3c150001, 0x30620800, 0x54400001, 0x3c150002, 0x3c028000, 0x2621025,
-0x2be1825, 0x10000007, 0x439825, 0x3c130001, 0x2719821, 0x8e73549c,
-0x3c027fff, 0x3442ffff, 0x2629824, 0x8fa7001c, 0x71140, 0x3c010001,
-0x220821, 0xac335494, 0x1000004b, 0x2601021, 0x8fa7001c, 0x72140,
-0x3c030001, 0x641821, 0x8c635498, 0x3c024000, 0x621024, 0x14400008,
-0x3c027fff, 0x3442ffff, 0x629824, 0x3c010001, 0x240821, 0xac335490,
-0x1000003b, 0x2601021, 0x3c020001, 0x8c4232bc, 0x1040002e, 0x3c13c00c,
-0x3c020001, 0x8c4233c8, 0x3c03e00c, 0x3c010001, 0x240821, 0x8c2454a4,
-0x2102b, 0x21023, 0x431024, 0x10800004, 0x539825, 0x3c020020,
-0x10000004, 0x2629825, 0x3c02ffdf, 0x3442ffff, 0x2629824, 0x8fa7001c,
-0x71140, 0x3c010001, 0x220821, 0x8c2254ac, 0x10400003, 0x3c020080,
-0x10000004, 0x2629825, 0x3c02ff7f, 0x3442ffff, 0x2629824, 0x3c020001,
-0x8c423320, 0x10400002, 0x3c020800, 0x2629825, 0x3c020001, 0x8c423324,
-0x10400002, 0x3c020400, 0x2629825, 0x3c020001, 0x8c423328, 0x10400006,
-0x3c020100, 0x10000004, 0x2629825, 0x3c027fff, 0x3442ffff, 0x629824,
-0x8fa7001c, 0x71140, 0x3c010001, 0x220821, 0xac335490, 0x2601021,
-0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008,
-0x27bd0038, 0x27bdffe0, 0xafb50018, 0x80a821, 0xafbf001c, 0xafb30014,
-0xafb10010, 0x8f840200, 0x3c030001, 0x8c6332ac, 0x8f860220, 0x24020002,
-0x106200a3, 0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 0x151940,
-0x1000009d, 0x0, 0x24020004, 0x10620053, 0x24020008, 0x10620052,
-0x159940, 0x10000096, 0x0, 0x3c050001, 0xa32821, 0x8ca5549c,
-0x3c110001, 0x2238821, 0x8e315494, 0x3c024000, 0xa21024, 0x10400038,
-0x3c020008, 0x2221024, 0x10400020, 0x34840002, 0x3c020001, 0x431021,
-0x8c4254a0, 0x10400005, 0x34840020, 0x34840100, 0x3c020020, 0x10000006,
-0x2228825, 0x2402feff, 0x822024, 0x3c02ffdf, 0x3442ffff, 0x2228824,
-0x151140, 0x3c010001, 0x220821, 0x8c2254a8, 0x10400005, 0x3c020001,
-0xc23025, 0x3c020080, 0x10000016, 0x2228825, 0x3c02fffe, 0x3442ffff,
-0xc23024, 0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2228824, 0x2402fedf,
-0x822024, 0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff,
-0x2228824, 0x3c010001, 0x230821, 0xac2054a0, 0x3c010001, 0x230821,
-0xac2054a8, 0xaf840200, 0xaf860220, 0x8f820220, 0x34420002, 0xaf820220,
-0x1000000a, 0x151140, 0x3c02bfff, 0x3442ffff, 0x8f830200, 0x2228824,
-0x2402fffd, 0x621824, 0xc003a65, 0xaf830200, 0x151140, 0x3c010001,
-0x220821, 0x10000048, 0xac315494, 0x159940, 0x3c050001, 0xb32821,
-0x8ca55498, 0x3c110001, 0x2338821, 0x8e315490, 0x3c024000, 0xa21024,
-0x14400010, 0x0, 0x3c020001, 0x8c4233c8, 0x14400005, 0x3c02bfff,
-0x8f820200, 0x34420002, 0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003a65,
-0x2228824, 0x3c010001, 0x330821, 0x1000002e, 0xac315490, 0x3c020001,
-0x8c4233c8, 0x14400027, 0x151140, 0x3c020020, 0xa21024, 0x10400007,
-0x34840020, 0x24020100, 0x3c010001, 0x330821, 0xac2254a4, 0x10000006,
-0x34840100, 0x3c010001, 0x330821, 0xac2054a4, 0x2402feff, 0x822024,
-0x3c020080, 0xa21024, 0x10400007, 0x151940, 0x3c020001, 0x3c010001,
-0x230821, 0xac2254ac, 0x10000008, 0xc23025, 0x151140, 0x3c010001,
-0x220821, 0xac2054ac, 0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200,
-0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 0x151140, 0x3c010001,
-0x220821, 0xac315490, 0x8fbf001c, 0x8fb50018, 0x8fb30014, 0x8fb10010,
-0x3e00008, 0x27bd0020, 0x0, 0x0, 0x1821, 0x308400ff,
-0x2405ffdf, 0x2406ffbf, 0x641007, 0x30420001, 0x10400004, 0x0,
-0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, 0xaf820044,
-0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 0x451024, 0xaf820044,
-0x24630001, 0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 0x0,
-0x0, 0x0, 0x0 };
-u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] = {
+0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff,
+0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044,
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023,
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff,
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001,
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008,
+0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x8ee379c8, 0x24020008,
+0x146201ca, 0x0, 0x3c020001, 0x8c423528, 0x14400005, 0x0,
+0xc003ab1, 0x8f840224, 0x100001c2, 0x0, 0x8f820220, 0x3c030008,
+0x431024, 0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 0x3c030400,
+0x431024, 0x10400006, 0x0, 0x3c010001, 0xac2055a0, 0x3c010001,
+0x1000000b, 0xac2055c0, 0x3c030001, 0x246355a0, 0x8c620000, 0x24420001,
+0xac620000, 0x2c420002, 0x14400003, 0x24020001, 0x3c010001, 0xac2255c0,
+0x3c020001, 0x8c4255c0, 0x10400006, 0x30820040, 0x10400004, 0x24020001,
+0x3c010001, 0x10000003, 0xac2255c4, 0x3c010001, 0xac2055c4, 0x3c010001,
+0xac24559c, 0x3c010001, 0x1000000b, 0xac2055d0, 0x3c010001, 0xac2255d0,
+0x3c010001, 0xac2055c0, 0x3c010001, 0xac2055a0, 0x3c010001, 0xac2055c4,
+0x3c010001, 0xac20559c, 0x3c030001, 0x8c635590, 0x3c020001, 0x8c425594,
+0x50620004, 0x2463ffff, 0x3c010001, 0xac235594, 0x2463ffff, 0x2c62000e,
+0x1040017e, 0x31080, 0x3c010001, 0x220821, 0x8c2232b0, 0x400008,
+0x0, 0x3c02fdff, 0x3442ffff, 0x282a024, 0x24020002, 0x3c010001,
+0xac2055c0, 0x3c010001, 0xac2055a0, 0x3c010001, 0xac2055d0, 0x3c010001,
+0xac20559c, 0x3c010001, 0xac2055c4, 0x3c010001, 0xac2055b8, 0x3c010001,
+0xac2055b0, 0xaf800224, 0x3c010001, 0xac225590, 0xc003ab1, 0x0,
+0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001,
+0xac2055e0, 0x8f830054, 0x3c020001, 0x8c4255b8, 0x24040001, 0x3c010001,
+0xac2455cc, 0x24420001, 0x3c010001, 0xac2255b8, 0x2c420004, 0x3c010001,
+0xac2355b4, 0x14400006, 0x24020003, 0x3c010001, 0xac243410, 0x3c010001,
+0x10000148, 0xac2055b8, 0x3c010001, 0x10000145, 0xac225590, 0x8f830054,
+0x3c020001, 0x8c4255b4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440013d,
+0x24020004, 0x3c010001, 0x1000013a, 0xac225590, 0x3c040001, 0x8c84352c,
+0x3c010001, 0xc00464e, 0xac2055a8, 0x3c020001, 0x8c4255dc, 0xaf820204,
+0x8f820204, 0x30420030, 0x14400125, 0x24020002, 0x3c030001, 0x8c6355dc,
+0x24020005, 0x3c010001, 0xac225590, 0x3c010001, 0x10000126, 0xac2355e0,
+0x3c020001, 0x8c4255c0, 0x10400122, 0x0, 0x3c020001, 0x8c42559c,
+0x1040011e, 0x0, 0x3c010001, 0xac2255c8, 0x24020003, 0x3c010001,
+0xac2255a0, 0x100000c1, 0x24020006, 0x3c010001, 0xac2055a8, 0x8f820204,
+0x34420040, 0xaf820204, 0x3c020001, 0x8c4255e0, 0x24030007, 0x3c010001,
+0xac235590, 0x34420040, 0x3c010001, 0xac2255e0, 0x3c020001, 0x8c4255c0,
+0x10400005, 0x0, 0x3c020001, 0x8c42559c, 0x104000f9, 0x24020002,
+0x3c050001, 0x24a555a0, 0x8ca20000, 0x2c424e21, 0x104000f3, 0x24020002,
+0x3c020001, 0x8c4255c4, 0x104000f8, 0x2404ffbf, 0x3c020001, 0x8c42559c,
+0x3c030001, 0x8c6355c8, 0x441024, 0x641824, 0x14430007, 0x24020001,
+0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 0x100000ea, 0xac225590,
+0x3c010001, 0x100000e7, 0xac225590, 0x3c020001, 0x8c4255cc, 0x1040000c,
+0x24020001, 0x3c040001, 0xc00465b, 0x8c84559c, 0x3c020001, 0x8c4255e8,
+0x14400005, 0x24020001, 0x3c020001, 0x8c4255e4, 0x10400006, 0x24020001,
+0x3c010001, 0xac223410, 0x3c010001, 0x100000d3, 0xac2055b8, 0x8f820204,
+0x34420040, 0xaf820204, 0x3c020001, 0x8c4255e0, 0x3c030001, 0x8c6355b0,
+0x34420040, 0x3c010001, 0xac2255e0, 0x3c020001, 0x8c42559c, 0x2c630001,
+0x318c0, 0x3c010001, 0xac2355b0, 0x30420008, 0x3c010001, 0xac2255ac,
+0x8f830054, 0x24020009, 0x3c010001, 0xac225590, 0x3c010001, 0x100000b9,
+0xac2355b4, 0x8f830054, 0x3c020001, 0x8c4255b4, 0x2463d8f0, 0x431023,
+0x2c422710, 0x1440009f, 0x0, 0x3c020001, 0x8c4255c0, 0x10400005,
+0x0, 0x3c020001, 0x8c42559c, 0x104000a0, 0x24020002, 0x3c030001,
+0x246355a0, 0x8c620000, 0x2c424e21, 0x1040009a, 0x24020002, 0x3c020001,
+0x8c4255cc, 0x1040000e, 0x0, 0x3c020001, 0x8c42559c, 0x3c010001,
+0xac2055cc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080,
+0x1440000c, 0x24020003, 0x10000029, 0x2402000c, 0x3c020001, 0x8c42559c,
+0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f,
+0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 0xac225590, 0x3c040001,
+0x248455d8, 0x8c820000, 0x3c030001, 0x8c6355b0, 0x431025, 0xaf820204,
+0x8c830000, 0x3c040001, 0x8c8455b0, 0x2402000b, 0x3c010001, 0xac225590,
+0x641825, 0x3c010001, 0xac2355e0, 0x3c050001, 0x24a555a0, 0x8ca20000,
+0x2c424e21, 0x10400066, 0x24020002, 0x3c020001, 0x8c4255d0, 0x10400005,
+0x0, 0x2402000c, 0x3c010001, 0x10000067, 0xac225590, 0x3c020001,
+0x8c4255c0, 0x10400063, 0x0, 0x3c040001, 0x8c84559c, 0x10800055,
+0x30820008, 0x3c030001, 0x8c6355ac, 0x1062005b, 0x24020003, 0x3c010001,
+0xac2455c8, 0xaca20000, 0x24020006, 0x3c010001, 0x10000054, 0xac225590,
+0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001,
+0xac225590, 0x3c010001, 0xac2355b4, 0x8f830054, 0x3c020001, 0x8c4255b4,
+0x2463d8f0, 0x431023, 0x2c422710, 0x14400031, 0x0, 0x3c020001,
+0x8c4255d0, 0x10400020, 0x2402000e, 0x3c030001, 0x8c6355e4, 0x3c010001,
+0x14600015, 0xac225590, 0xc003b6a, 0x0, 0x3c050001, 0x8ca5340c,
+0xc0047d1, 0x24040001, 0x3c030001, 0x8c63340c, 0x24020004, 0x14620005,
+0x2403fffb, 0x3c020001, 0x8c423408, 0x10000003, 0x2403fff7, 0x3c020001,
+0x8c423408, 0x431024, 0x3c010001, 0xac223408, 0x8f830224, 0x3c020200,
+0x3c010001, 0xac2355ec, 0x10000020, 0x282a025, 0x3c020001, 0x8c4255c0,
+0x10400005, 0x0, 0x3c020001, 0x8c42559c, 0x1040000f, 0x24020002,
+0x3c020001, 0x8c4255a0, 0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001,
+0x8c4255c0, 0x1040000f, 0x0, 0x3c020001, 0x8c42559c, 0x1440000b,
+0x0, 0x24020002, 0x3c010001, 0x10000007, 0xac225590, 0x3c020001,
+0x8c4255c0, 0x10400003, 0x0, 0xc003ab1, 0x0, 0x8f820220,
+0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018,
+0x3c030001, 0x246355e8, 0x8c620000, 0x10400005, 0x34422000, 0x3c010001,
+0xac2255dc, 0x10000003, 0xac600000, 0x3c010001, 0xac2455dc, 0x3e00008,
+0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001, 0xac2255e4,
+0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030,
+0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200,
+0x3c040001, 0x8c84352c, 0x621825, 0x331c2, 0x3c030001, 0x2463348c,
+0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2,
+0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025,
+0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c,
+0x3c05000f, 0x10000037, 0x0, 0x8f820200, 0x2403feff, 0x431024,
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220,
+0x3c010001, 0xac205624, 0x3c010001, 0x10000034, 0xac20562c, 0x8f820200,
+0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024,
+0xaf820220, 0x24020100, 0x3c010001, 0xac225624, 0x3c010001, 0x10000026,
+0xac20562c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 0xac205624, 0x3c010001,
+0x10000019, 0xac23562c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220,
+0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, 0xac225624,
+0x3c010001, 0x1000000c, 0xac23562c, 0x34a5ffff, 0x3c040001, 0x248432e8,
+0xafa30010, 0xc00290f, 0xafa00014, 0x10000004, 0x0, 0x24020030,
+0x3c010001, 0xac2255e8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0,
+0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c, 0xa0f021, 0xafb10020,
+0xc08821, 0x3c040001, 0x24843300, 0x3c050009, 0x3c020001, 0x8c42340c,
+0x34a59001, 0x2603021, 0x3c03821, 0xafbf0030, 0xafb50028, 0xa7a0001a,
+0xafb10014, 0xc00290f, 0xafa20010, 0x24020002, 0x13c200e7, 0x2fc20003,
+0x10400005, 0x24020001, 0x13c2000a, 0x3c02fffb, 0x100000e1, 0x0,
+0x24020004, 0x13c2006d, 0x24020008, 0x13c2006c, 0x3c02ffec, 0x100000da,
+0x0, 0x3442ffff, 0x2228824, 0x13a940, 0x3c010001, 0x350821,
+0xac3155fc, 0x3c024000, 0x2221024, 0x10400046, 0x1123c2, 0x30840030,
+0x111382, 0x3042000c, 0x3c030001, 0x24633434, 0x431021, 0x823821,
+0x3c020020, 0x2221024, 0x10400006, 0x24020100, 0x3c010001, 0x350821,
+0xac225600, 0x10000005, 0x3c020080, 0x3c010001, 0x350821, 0xac205600,
+0x3c020080, 0x2221024, 0x10400006, 0x131940, 0x3c020001, 0x3c010001,
+0x230821, 0x10000005, 0xac225608, 0x131140, 0x3c010001, 0x220821,
+0xac205608, 0x94e30000, 0x32224000, 0x10400003, 0xa7a30018, 0x34624000,
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 0x24e60002, 0x34420001,
+0xc004076, 0xa4e20002, 0x24040001, 0x2821, 0xc004076, 0x27a60018,
+0x3c020001, 0x8c42340c, 0x24130001, 0x3c010001, 0xac333418, 0x145e0004,
+0x32228000, 0xc003ab1, 0x0, 0x32228000, 0x10400093, 0x0,
+0xc003ab1, 0x0, 0x24020002, 0x3c010001, 0xac333410, 0x3c010001,
+0x1000008b, 0xac22340c, 0x24040001, 0x24050004, 0x27b1001a, 0xc004076,
+0x2203021, 0x24040001, 0x2821, 0xc004076, 0x2203021, 0x3c020001,
+0x551021, 0x8c4255f4, 0x3c040001, 0x8c84340c, 0x3c03bfff, 0x3463ffff,
+0x3c010001, 0xac3e3418, 0x431024, 0x3c010001, 0x350821, 0x109e0072,
+0xac2255f4, 0x10000072, 0x0, 0x3c02ffec, 0x3442ffff, 0x2228824,
+0x3c020008, 0x2228825, 0x131140, 0x3c010001, 0x220821, 0xac3155f8,
+0x3c022000, 0x2221024, 0x10400005, 0x24020001, 0x3c010001, 0xac223528,
+0x10000004, 0x3c024000, 0x3c010001, 0xac203528, 0x3c024000, 0x2221024,
+0x1440001a, 0x0, 0x3c020001, 0x8c423528, 0x10400005, 0x24022020,
+0x3c010001, 0xac22352c, 0x24020001, 0xaee279c8, 0x3c04bfff, 0x131940,
+0x3c020001, 0x431021, 0x8c4255f0, 0x3c050001, 0x8ca5340c, 0x3484ffff,
+0x441024, 0x3c010001, 0x230821, 0xac2255f0, 0x24020001, 0x10a20044,
+0x0, 0x10000040, 0x0, 0x3c020001, 0x8c423528, 0x1040001c,
+0x24022000, 0x3c010001, 0xac22352c, 0x3c0300a0, 0x2231024, 0x14430005,
+0x131140, 0x3402a000, 0x3c010001, 0x1000002d, 0xac22352c, 0x3c030001,
+0x621821, 0x8c6355f8, 0x3c020020, 0x621024, 0x10400004, 0x24022001,
+0x3c010001, 0x10000023, 0xac22352c, 0x3c020080, 0x621024, 0x1040001f,
+0x3402a001, 0x3c010001, 0x1000001c, 0xac22352c, 0x3c020020, 0x2221024,
+0x10400007, 0x131940, 0x24020100, 0x3c010001, 0x230821, 0xac225604,
+0x10000006, 0x3c020080, 0x131140, 0x3c010001, 0x220821, 0xac205604,
+0x3c020080, 0x2221024, 0x10400006, 0x131940, 0x3c020001, 0x3c010001,
+0x230821, 0x10000005, 0xac22560c, 0x131140, 0x3c010001, 0x220821,
+0xac20560c, 0x3c030001, 0x8c63340c, 0x24020001, 0x10620003, 0x0,
+0xc003ab1, 0x0, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024,
+0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffc8, 0xafb50028, 0xa821,
+0xafbe002c, 0xf021, 0xafb30024, 0x9821, 0x24020002, 0xafbf0030,
+0xafb10020, 0xafa4001c, 0xa7a00012, 0x10a2006a, 0xa7a00010, 0x2ca20003,
+0x10400005, 0x24020001, 0x10a2000a, 0x3c024000, 0x100000ad, 0x2601021,
+0x24020004, 0x10a20060, 0x24020008, 0x10a2005e, 0x2601021, 0x100000a6,
+0x0, 0x8fa7001c, 0x78940, 0x3c030001, 0x711821, 0x8c6355fc,
+0x621024, 0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 0x629824,
+0x3c010001, 0x310821, 0xac3355f4, 0x10000096, 0x2601021, 0x24050001,
+0xc004034, 0x27a60010, 0x24040001, 0x24050001, 0xc004034, 0x27a60010,
+0x97a20010, 0x30420004, 0x10400034, 0x3c134000, 0x3c030001, 0x8c63353c,
+0x24020003, 0x10620008, 0x2c620004, 0x14400029, 0x3c028000, 0x24020004,
+0x10620014, 0x24040001, 0x10000024, 0x3c028000, 0x24040001, 0x24050011,
+0x27b10012, 0xc004034, 0x2203021, 0x24040001, 0x24050011, 0xc004034,
+0x2203021, 0x97a30012, 0x30624000, 0x10400002, 0x3c1e0010, 0x3c1e0008,
+0x3c150001, 0x10000010, 0x30628000, 0x24050014, 0x27b10012, 0xc004034,
+0x2203021, 0x24040001, 0x24050014, 0xc004034, 0x2203021, 0x97a30012,
+0x30621000, 0x10400002, 0x3c1e0010, 0x3c1e0008, 0x3c150001, 0x30620800,
+0x54400001, 0x3c150002, 0x3c028000, 0x2621025, 0x2be1825, 0x10000007,
+0x439825, 0x3c130001, 0x2719821, 0x8e7355fc, 0x3c027fff, 0x3442ffff,
+0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, 0x220821, 0xac3355f4,
+0x1000004b, 0x2601021, 0x8fa7001c, 0x72140, 0x3c030001, 0x641821,
+0x8c6355f8, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff,
+0x629824, 0x3c010001, 0x240821, 0xac3355f0, 0x1000003b, 0x2601021,
+0x3c020001, 0x8c42341c, 0x1040002e, 0x3c13c00c, 0x3c020001, 0x8c423528,
+0x3c03e00c, 0x3c010001, 0x240821, 0x8c245604, 0x2102b, 0x21023,
+0x431024, 0x10800004, 0x539825, 0x3c020020, 0x10000004, 0x2629825,
+0x3c02ffdf, 0x3442ffff, 0x2629824, 0x8fa7001c, 0x71140, 0x3c010001,
+0x220821, 0x8c22560c, 0x10400003, 0x3c020080, 0x10000004, 0x2629825,
+0x3c02ff7f, 0x3442ffff, 0x2629824, 0x3c020001, 0x8c423480, 0x10400002,
+0x3c020800, 0x2629825, 0x3c020001, 0x8c423484, 0x10400002, 0x3c020400,
+0x2629825, 0x3c020001, 0x8c423488, 0x10400006, 0x3c020100, 0x10000004,
+0x2629825, 0x3c027fff, 0x3442ffff, 0x629824, 0x8fa7001c, 0x71140,
+0x3c010001, 0x220821, 0xac3355f0, 0x2601021, 0x8fbf0030, 0x8fbe002c,
+0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffe0,
+0xafb50018, 0x80a821, 0xafbf001c, 0xafb30014, 0xafb10010, 0x8f840200,
+0x3c030001, 0x8c63340c, 0x8f860220, 0x24020002, 0x106200a3, 0x2c620003,
+0x10400005, 0x24020001, 0x1062000a, 0x151940, 0x1000009d, 0x0,
+0x24020004, 0x10620053, 0x24020008, 0x10620052, 0x159940, 0x10000096,
+0x0, 0x3c050001, 0xa32821, 0x8ca555fc, 0x3c110001, 0x2238821,
+0x8e3155f4, 0x3c024000, 0xa21024, 0x10400038, 0x3c020008, 0x2221024,
+0x10400020, 0x34840002, 0x3c020001, 0x431021, 0x8c425600, 0x10400005,
+0x34840020, 0x34840100, 0x3c020020, 0x10000006, 0x2228825, 0x2402feff,
+0x822024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x151140, 0x3c010001,
+0x220821, 0x8c225608, 0x10400005, 0x3c020001, 0xc23025, 0x3c020080,
+0x10000016, 0x2228825, 0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff7f,
+0x3442ffff, 0x1000000f, 0x2228824, 0x2402fedf, 0x822024, 0x3c02fffe,
+0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2228824, 0x3c010001,
+0x230821, 0xac205600, 0x3c010001, 0x230821, 0xac205608, 0xaf840200,
+0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, 0x151140,
+0x3c02bfff, 0x3442ffff, 0x8f830200, 0x2228824, 0x2402fffd, 0x621824,
+0xc003ab1, 0xaf830200, 0x151140, 0x3c010001, 0x220821, 0x10000048,
+0xac3155f4, 0x159940, 0x3c050001, 0xb32821, 0x8ca555f8, 0x3c110001,
+0x2338821, 0x8e3155f0, 0x3c024000, 0xa21024, 0x14400010, 0x0,
+0x3c020001, 0x8c423528, 0x14400005, 0x3c02bfff, 0x8f820200, 0x34420002,
+0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003ab1, 0x2228824, 0x3c010001,
+0x330821, 0x1000002e, 0xac3155f0, 0x3c020001, 0x8c423528, 0x14400027,
+0x151140, 0x3c020020, 0xa21024, 0x10400007, 0x34840020, 0x24020100,
+0x3c010001, 0x330821, 0xac225604, 0x10000006, 0x34840100, 0x3c010001,
+0x330821, 0xac205604, 0x2402feff, 0x822024, 0x3c020080, 0xa21024,
+0x10400007, 0x151940, 0x3c020001, 0x3c010001, 0x230821, 0xac22560c,
+0x10000008, 0xc23025, 0x151140, 0x3c010001, 0x220821, 0xac20560c,
+0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, 0xaf860220, 0x8f820220,
+0x34420002, 0xaf820220, 0x151140, 0x3c010001, 0x220821, 0xac3155f0,
+0x8fbf001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0020,
+0x0, 0x0, 0x1821, 0x308400ff, 0x2405ffdf, 0x2406ffbf,
+0x641007, 0x30420001, 0x10400004, 0x0, 0x8f820044, 0x10000003,
+0x34420040, 0x8f820044, 0x461024, 0xaf820044, 0x8f820044, 0x34420020,
+0xaf820044, 0x8f820044, 0x451024, 0xaf820044, 0x24630001, 0x28620008,
+0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x0, 0x0,
+0x0 };
+u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000,
0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x0, 0x0,
0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 0x0,
@@ -5373,7 +5408,7 @@ u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] = {
0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x30001, 0x1,
0x30201, 0x0, 0x0 };
-u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = {
+u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x66776d61,
0x696e2e63, 0x2c762031, 0x2e312e34, 0x372e3420, 0x31393938, 0x2f31302f,
@@ -5429,12 +5464,14 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = {
0x0, 0x4d634465, 0x6c4e6f45, 0x0, 0x24486561, 0x6465723a,
0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963,
0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x646d612e, 0x632c7620, 0x312e312e,
-0x31322e31, 0x20313939, 0x382f3038, 0x2f303420, 0x32313a35, 0x343a3339,
+0x31322e33, 0x20313939, 0x382f3132, 0x2f303420, 0x32323a35, 0x313a3135,
0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x3f6e6f51, 0x64547845,
0x0, 0x3f6e6f51, 0x64527845, 0x0, 0x6576526e, 0x6746756c,
0x6c000000, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0,
0x6661696c, 0x456e454d, 0x0, 0x656e714d, 0x45764661, 0x696c0000,
0x656e714d, 0x45765046, 0x61696c00, 0x646d6172, 0x6441544e, 0x0,
+0x2a50414e, 0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73,
+0x72632f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f646d, 0x612e6300,
0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0,
0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x74726163,
@@ -5444,9 +5481,9 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = {
0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x64617461,
0x2e632c76, 0x20312e31, 0x2e322e34, 0x20313939, 0x382f3036, 0x2f323320,
0x30313a32, 0x393a3330, 0x20736875, 0x616e6720, 0x45787020, 0x24000000,
-0x46575f56, 0x45525349, 0x4f4e3a20, 0x23312046, 0x7269204f, 0x63742031,
-0x36203130, 0x3a31353a, 0x30362050, 0x44542031, 0x39393800, 0x46575f43,
-0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031303a, 0x31353a30, 0x36000000,
+0x46575f56, 0x45525349, 0x4f4e3a20, 0x2331204d, 0x6f6e2044, 0x65632037,
+0x2031343a, 0x35383a32, 0x34205053, 0x54203139, 0x39380000, 0x46575f43,
+0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031343a, 0x35383a32, 0x34000000,
0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000,
0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465,
0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065,
@@ -5469,20 +5506,20 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = {
0x756e6b72, 0x64747970, 0x65000000, 0x3f546370, 0x436b7375, 0x6d000000,
0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d,
-0x6d6f6e2f, 0x72656376, 0x2e632c76, 0x20312e31, 0x2e322e33, 0x35203139,
-0x39382f30, 0x372f3239, 0x2030303a, 0x30373a32, 0x37207368, 0x75616e67,
+0x6d6f6e2f, 0x72656376, 0x2e632c76, 0x20312e31, 0x2e34322e, 0x33203139,
+0x39382f31, 0x322f3034, 0x2030303a, 0x31303a33, 0x38207368, 0x75616e67,
0x20457870, 0x20240000, 0x3f6e6f51, 0x64547845, 0x0, 0x3f6e6f51,
0x64527845, 0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x3f456e71,
0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6661696c, 0x456e454d,
0x0, 0x656e714d, 0x45764661, 0x696c0000, 0x656e714d, 0x45765046,
0x61696c00, 0x66726d32, 0x4c617267, 0x65000000, 0x72784e6f, 0x52784264,
-0x0, 0x72785144, 0x6d614446, 0x0, 0x72785144, 0x6d614246,
-0x0, 0x3f724264, 0x446d6146, 0x0, 0x3f724a42, 0x64446d46,
-0x0, 0x0, 0xdabc, 0xdabc, 0xdabc, 0xdabc,
-0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc,
-0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdaac,
-0xdaac, 0xdaac, 0xdabc, 0xdabc, 0xdabc, 0xdabc,
-0xdabc, 0xdabc, 0x572d444d, 0x41456e46, 0x0, 0x0,
+0x0, 0x72785144, 0x6d447446, 0x0, 0x72785144, 0x6d614446,
+0x0, 0x72785144, 0x6d614246, 0x0, 0x3f724264, 0x446d6146,
+0x0, 0x3f724a42, 0x64446d46, 0x0, 0xdbe8, 0xdbe8,
+0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8,
+0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8,
+0xdbe8, 0xdbd8, 0xdbd8, 0xdbd8, 0xdbe8, 0xdbe8,
+0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0x572d444d, 0x41456e46,
0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563,
0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d,
0x6d6f6e2f, 0x6d61632e, 0x632c7620, 0x312e312e, 0x31372e31, 0x20313939,
@@ -5503,15 +5540,15 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = {
0x64457650, 0x0, 0x6661696c, 0x456e454d, 0x0, 0x656e714d,
0x45764661, 0x696c0000, 0x656e714d, 0x45765046, 0x61696c00, 0x0,
0x50726f62, 0x65506879, 0x0, 0x6c6e6b41, 0x53535254, 0x0,
-0xf81c, 0xf84c, 0xf870, 0xf89c, 0xf8c8, 0xf8dc,
-0xf918, 0xfca0, 0xf9c8, 0xfaf4, 0xfa14, 0xfb4c,
-0xfb74, 0xfba8, 0xfa58, 0xfca0, 0xfac0, 0xfaf4,
-0xfb1c, 0xfb4c, 0xfb74, 0xfba8, 0xfbe4, 0x0,
-0x0, 0x0, 0x101fc, 0x102cc, 0x103a4, 0x10474,
-0x104d0, 0x105ac, 0x105d4, 0x106b0, 0x106d8, 0x10880,
-0x108a8, 0x10a50, 0x10c48, 0x10edc, 0x10df0, 0x10edc,
-0x10f08, 0x10a78, 0x10c20, 0x0, 0x1120c, 0x11260,
-0x112dc, 0x11308, 0x11358, 0x11394, 0x113c8, 0x11454,
-0x1150c, 0x115dc, 0x1161c, 0x116a0, 0x116c4, 0x117d4,
+0xf94c, 0xf97c, 0xf9a0, 0xf9cc, 0xf9f8, 0xfa0c,
+0xfa48, 0xfdd0, 0xfaf8, 0xfc24, 0xfb44, 0xfc7c,
+0xfca4, 0xfcd8, 0xfb88, 0xfdd0, 0xfbf0, 0xfc24,
+0xfc4c, 0xfc7c, 0xfca4, 0xfcd8, 0xfd14, 0x0,
+0x0, 0x0, 0x1032c, 0x103fc, 0x104d4, 0x105a4,
+0x10600, 0x106dc, 0x10704, 0x107e0, 0x10808, 0x109b0,
+0x109d8, 0x10b80, 0x10d78, 0x1100c, 0x10f20, 0x1100c,
+0x11038, 0x10ba8, 0x10d50, 0x0, 0x1133c, 0x11390,
+0x1140c, 0x11438, 0x11488, 0x114c4, 0x114f8, 0x11584,
+0x1163c, 0x1170c, 0x1174c, 0x117d0, 0x117f4, 0x11904,
0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0,
0x73746d61, 0x634c4e4b, 0x0, 0x0, 0x0 };
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index d3578f5da..f4e682f4d 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -119,22 +119,26 @@ static int init_pcmcia(void);
static const char *version =
"apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
+static int apne_owned = 0; /* signal if card already owned */
__initfunc(int apne_probe(struct device *dev))
{
#ifndef MANUAL_CONFIG
char tuple[8];
#endif
+
+ if (apne_owned)
+ return -ENODEV;
if ( !(AMIGAHW_PRESENT(PCMCIA)) )
- return (ENODEV);
+ return (-ENODEV);
printk("Looking for PCMCIA ethernet card : ");
/* check if a card is inserted */
if (!(PCMCIA_INSERTED)) {
printk("NO PCMCIA card inserted\n");
- return (ENODEV);
+ return (-ENODEV);
}
/* disable pcmcia irq for readtuple */
@@ -144,7 +148,7 @@ __initfunc(int apne_probe(struct device *dev))
if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
(tuple[2] != CISTPL_FUNCID_NETWORK)) {
printk("not an ethernet card\n");
- return (ENODEV);
+ return (-ENODEV);
}
#endif
@@ -153,7 +157,7 @@ __initfunc(int apne_probe(struct device *dev))
if (init_pcmcia())
return apne_probe1(dev, IOBASE+GAYLE_IO);
else
- return (ENODEV);
+ return (-ENODEV);
}
@@ -169,7 +173,7 @@ __initfunc(static int apne_probe1(struct device *dev, int ioaddr))
int neX000, ctron;
#endif
static unsigned version_printed = 0;
- static int pcmcia_offsets[16]={
+ static u32 pcmcia_offsets[16]={
0, 1+GAYLE_ODD, 2, 3+GAYLE_ODD,
4, 5+GAYLE_ODD, 6, 7+GAYLE_ODD,
8, 9+GAYLE_ODD, 0xa, 0xb+GAYLE_ODD,
@@ -197,7 +201,7 @@ __initfunc(static int apne_probe1(struct device *dev, int ioaddr))
while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
if (jiffies - reset_start_time > 2*HZ/100) {
printk(" not found (no reset ack).\n");
- return ENODEV;
+ return -ENODEV;
}
writeb(0xff, ioaddr + NE_EN0_ISR); /* Ack all intr. */
@@ -328,6 +332,8 @@ __initfunc(static int apne_probe1(struct device *dev, int ioaddr))
pcmcia_ack_int(pcmcia_get_intreq()); /* ack PCMCIA int req */
pcmcia_enable_irq();
+ apne_owned = 1;
+
return 0;
}
@@ -390,7 +396,7 @@ apne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+ "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
dev->interrupt);
return;
@@ -439,7 +445,7 @@ apne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_of
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+ "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
dev->interrupt);
return;
@@ -488,7 +494,7 @@ apne_block_output(struct device *dev, int count,
/* This *shouldn't* happen. If it does, it's the last thing you'll see */
if (ei_status.dmaing) {
printk("%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+ "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
dev->name, ei_status.dmaing, ei_status.irqlock,
dev->interrupt);
return;
@@ -577,15 +583,17 @@ int init_module(void)
void cleanup_module(void)
{
+ unregister_netdev(&apne_dev);
+
pcmcia_disable_irq();
free_irq(IRQ_AMIGA_PORTS, &apne_dev);
pcmcia_reset();
- unregister_netdev(&apne_dev);
-
unlock_8390_module();
+
+ apne_owned = 0;
}
#endif
diff --git a/drivers/net/ariadne2.c b/drivers/net/ariadne2.c
index 0b71b5987..c58a90932 100644
--- a/drivers/net/ariadne2.c
+++ b/drivers/net/ariadne2.c
@@ -33,6 +33,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/amigaints.h>
+#include <asm/amigahw.h>
#include "8390.h"
@@ -107,7 +108,7 @@ __initfunc(static int ariadne2_init(struct device *dev, unsigned int key,
unsigned char SA_prom[32];
const char *name = NULL;
int start_page, stop_page;
- static int ariadne2_offsets[16] = {
+ static u32 ariadne2_offsets[16] = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
@@ -417,7 +418,7 @@ void cleanup_module(void)
unsigned int key = ((struct ei_device *)ariadne2_dev.priv)->priv;
free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev);
unregister_netdev(&ariadne2_dev);
- zorro_config_board(key, 0);
+ zorro_unconfig_board(key, 0);
unlock_8390_module();
}
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 77641a0f4..9ba40dd13 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -12,8 +12,12 @@
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
- This is a device driver for the Allied Telesis AT1700, which is a
- straight-forward Fujitsu MB86965 implementation.
+ This is a device driver for the Allied Telesis AT1700, and
+ Fujitsu FMV-181/182/181A/182A/183/184/183A/184A, which are
+ straight-forward Fujitsu MB86965 implementations.
+
+ Modification for Fujitsu FMV-18X cards is done by Yutaka Tamiya
+ (tamy@flab.fujitsu.co.jp).
Sources:
The Fujitsu MB86965 datasheet.
@@ -81,7 +85,7 @@ static int at1700_probe_list[] = {
/*
* MCA
*/
-
+#ifdef CONFIG_MCA
static int at1700_ioaddr_pattern[] = {
0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
};
@@ -94,6 +98,7 @@ static int at1700_irq_pattern[] = {
0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
};
+#endif
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
@@ -109,6 +114,8 @@ struct net_local {
unsigned char mc_filter[8];
uint jumpered:1; /* Set iff the board has jumper config. */
uint tx_started:1; /* Packets are on the Tx queue. */
+ uint tx_queue_ready:1; /* Tx queue is ready to be sent. */
+ uint rx_started:1; /* Packets are Rxing. */
uint invalid_irq:1;
uchar tx_queue; /* Number of packet on the Tx queue. */
char mca_slot; /* -1 means ISA */
@@ -129,10 +136,13 @@ struct net_local {
/* Run-time register bank 2 definitions. */
#define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */
#define TX_START 10
+#define COL16CNTL 11 /* Controll Reg for 16 collisions */
#define MODE13 13
/* Configuration registers only on the '865A/B chips. */
#define EEPROM_Ctrl 16
#define EEPROM_Data 17
+#define CARDSTATUS 16 /* FMV-18x Card Status */
+#define CARDSTATUS1 17 /* FMV-18x Card Status */
#define IOCONFIG 18 /* Either read the jumper, or move the I/O. */
#define IOCONFIG1 19
#define SAPROM 20 /* The station address PROM, if no EEPROM. */
@@ -214,9 +224,9 @@ int at1700_probe(struct device *dev)
int at1700_probe1(struct device *dev, int ioaddr)
{
char fmv_irqmap[4] = {3, 7, 10, 15};
+ char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
- int l_i;
int slot;
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
@@ -238,16 +248,17 @@ int at1700_probe1(struct device *dev, int ioaddr)
/* redone for multi-card detection by ZP Gu (zpg@castle.net) */
/* now works as a module */
- if( MCA_bus ) {
+ if (MCA_bus) {
int j;
+ int l_i;
u_char pos3, pos4;
- for( j = 0; at1720_mca_adapters[j].name != NULL; j ++ ) {
+ for (j = 0; at1720_mca_adapters[j].name != NULL; j ++) {
slot = 0;
- while( slot != MCA_NOTFOUND ) {
+ while (slot != MCA_NOTFOUND) {
slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
- if( slot == MCA_NOTFOUND ) break;
+ if (slot == MCA_NOTFOUND) break;
/* if we get this far, an adapter has been detected and is
enabled */
@@ -292,15 +303,16 @@ int at1700_probe1(struct device *dev, int ioaddr)
&& read_eeprom(ioaddr, 4) == 0x0000
&& (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400)
is_at1700 = 1;
- else if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] == ioaddr
- && inb(ioaddr + SAPROM ) == 0x00
+ else if (inb(ioaddr + SAPROM ) == 0x00
&& inb(ioaddr + SAPROM + 1) == 0x00
&& inb(ioaddr + SAPROM + 2) == 0x0e)
is_fmv18x = 1;
else
return -ENODEV;
+#ifdef CONFIG_MCA
found:
+#endif
/* Reset the internal state machines. */
outb(0, ioaddr + RESET);
@@ -312,24 +324,46 @@ found:
if (is_at1700)
irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
| (read_eeprom(ioaddr, 0)>>14)];
- else
- if (is_fmv18x)
+ else {
+ /* Check PnP mode for FMV-183/184/183A/184A. */
+ /* This PnP routine is very poor. IO and IRQ should be known. */
+ if (inb(ioaddr + CARDSTATUS1) & 0x20) {
+ irq = dev->irq;
+ for (i = 0; i < 8; i++) {
+ if (irq == fmv_irqmap_pnp[i])
+ break;
+ }
+ if (i == 8)
+ return -ENODEV;
+ } else {
+ if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr)
+ return -ENODEV;
irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
-
+ }
+ }
+
/* Grab the region so that we can find another board if the IRQ request
fails. */
request_region(ioaddr, AT1700_IO_EXTENT, dev->name);
- printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
- ioaddr, irq);
+ printk("%s: %s found at %#3x, IRQ %d, address ", dev->name,
+ is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq);
dev->base_addr = ioaddr;
dev->irq = irq;
- for(i = 0; i < 3; i++) {
- unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
- printk("%04x", eeprom_val);
- ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
+ if (is_at1700) {
+ for(i = 0; i < 3; i++) {
+ unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
+ printk("%04x", eeprom_val);
+ ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
+ }
+ } else {
+ for(i = 0; i < 6; i++) {
+ unsigned char val = inb(ioaddr + SAPROM + i);
+ printk("%02x", val);
+ dev->dev_addr[i] = val;
+ }
}
/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
@@ -340,32 +374,44 @@ found:
*/
{
const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"};
- ushort setup_value = read_eeprom(ioaddr, 12);
-
- dev->if_port = setup_value >> 8;
+ if (is_at1700) {
+ ushort setup_value = read_eeprom(ioaddr, 12);
+ dev->if_port = setup_value >> 8;
+ } else {
+ ushort setup_value = inb(ioaddr + CARDSTATUS);
+ switch (setup_value & 0x07) {
+ case 0x01: /* 10base5 */
+ case 0x02: /* 10base2 */
+ dev->if_port = 0x18; break;
+ case 0x04: /* 10baseT */
+ dev->if_port = 0x08; break;
+ default: /* auto-sense */
+ dev->if_port = 0x00; break;
+ }
+ }
printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
}
+ /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
+ bus access, two 4K Tx queues, and disabled Tx and Rx. */
+ outb(0xda, ioaddr + CONFIG_0);
+
/* Set the station address in bank zero. */
- outb(0xe0, ioaddr + CONFIG_1);
+ outb(0x00, ioaddr + CONFIG_1);
for (i = 0; i < 6; i++)
outb(dev->dev_addr[i], ioaddr + 8 + i);
/* Switch to bank 1 and set the multicast table to accept none. */
- outb(0xe4, ioaddr + CONFIG_1);
+ outb(0x04, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++)
outb(0x00, ioaddr + 8 + i);
- /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
- bus access, two 4K Tx queues, and disabled Tx and Rx. */
- outb(0xda, ioaddr + CONFIG_0);
-
- /* Switch to bank 2 and lock our I/O address. */
- outb(0xe8, ioaddr + CONFIG_1);
- outb(dev->if_port, MODE13);
- /* Power-down the chip. Aren't we green! */
- outb(0x00, ioaddr + CONFIG_1);
+ /* Switch to bank 2 */
+ /* Lock our I/O address, and set manual processing mode for 16 collisions. */
+ outb(0x08, ioaddr + CONFIG_1);
+ outb(dev->if_port, ioaddr + MODE13);
+ outb(0x00, ioaddr + COL16CNTL);
if (net_debug)
printk(version);
@@ -456,35 +502,29 @@ static int net_open(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
- int i;
-
- /* Powerup the chip, initialize config register 1, and select bank 0. */
- outb(0xe0, ioaddr + CONFIG_1);
-
- /* Set the station address in bank zero. */
- for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + 8 + i);
-
- /* Switch to bank 1 and set the multicast table to accept none. */
- outb(0xe4, ioaddr + CONFIG_1);
- for (i = 0; i < 8; i++)
- outb(0x00, ioaddr + 8 + i);
/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
bus access, and two 4K Tx queues. */
- outb(0xda, ioaddr + CONFIG_0);
+ outb(0x5a, ioaddr + CONFIG_0);
- /* Switch to register bank 2, enable the Rx and Tx. */
- outw(0xe85a, ioaddr + CONFIG_0);
+ /* Powerup, switch to register bank 2, and enable the Rx and Tx. */
+ outb(0xe8, ioaddr + CONFIG_1);
lp->tx_started = 0;
+ lp->tx_queue_ready = 1;
+ lp->rx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
- /* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */
- outb(0x00, ioaddr + TX_INTR);
+ /* Turn on hardware Tx and Rx interrupts. */
+ outb(0x82, ioaddr + TX_INTR);
outb(0x81, ioaddr + RX_INTR);
+ /* Enable the IRQ on boards of fmv18x it is feasible. */
+ if (lp->jumpered) {
+ outb(0x80, ioaddr + IOCONFIG1);
+ }
+
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
@@ -518,10 +558,14 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
outw(0xffff, ioaddr + 24);
outw(0xffff, ioaddr + TX_STATUS);
outw(0xe85a, ioaddr + CONFIG_0);
- outw(0x8100, ioaddr + TX_INTR);
+ outw(0x8182, ioaddr + TX_INTR);
+ outb(0x00, ioaddr + TX_START);
+ outb(0x03, ioaddr + COL16CNTL);
dev->tbusy=0;
dev->trans_start = jiffies;
lp->tx_started = 0;
+ lp->tx_queue_ready = 1;
+ lp->rx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
}
@@ -534,14 +578,20 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
- /* Turn off the possible Tx interrupts. */
- outb(0x00, ioaddr + TX_INTR);
-
- outw(length, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
+ /* We may not start transmitting unless we finish transferring
+ a packet into the Tx queue. During executing the following
+ codes we possibly catch a Tx interrupt. Thus we flag off
+ tx_queue_ready, so that we prevent the interrupt routine
+ (net_interrupt) to start transmitting. */
+ lp->tx_queue_ready = 0;
+ {
+ outw(length, ioaddr + DATAPORT);
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
+ }
+ lp->tx_queue_ready = 1;
if (lp->tx_started == 0) {
/* If the Tx is idle, always trigger a transmit. */
@@ -554,9 +604,6 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
} else if (lp->tx_queue_len < 4096 - 1502)
/* Yes, there is room for one more packet. */
dev->tbusy = 0;
-
- /* Turn on Tx interrupts back on. */
- outb(0x82, ioaddr + TX_INTR);
}
dev_kfree_skb (skb);
@@ -585,14 +632,35 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (net_debug > 4)
printk("%s: Interrupt with status %04x.\n", dev->name, status);
- if (status & 0xff00
- || (inb(ioaddr + RX_MODE) & 0x40) == 0) { /* Got a packet(s). */
+ if (lp->rx_started == 0 &&
+ (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
+ /* Got a packet(s).
+ We cannot execute net_rx more than once at the same time for
+ the same device. During executing net_rx, we possibly catch a
+ Tx interrupt. Thus we flag on rx_started, so that we prevent
+ the interrupt routine (net_interrupt) to dive into net_rx
+ again. */
+ lp->rx_started = 1;
+ outb(0x00, ioaddr + RX_INTR); /* Disable RX intr. */
net_rx(dev);
+ outb(0x81, ioaddr + RX_INTR); /* Enable RX intr. */
+ lp->rx_started = 0;
}
if (status & 0x00ff) {
- if (status & 0x80) {
+ if (status & 0x02) {
+ /* More than 16 collisions occurred */
+ if (net_debug > 4)
+ printk("%s: 16 Collision occur during Txing.\n", dev->name);
+ /* Cancel sending a packet. */
+ outb(0x03, ioaddr + COL16CNTL);
+ lp->stats.collisions++;
+ }
+ if (status & 0x82) {
lp->stats.tx_packets++;
- if (lp->tx_queue) {
+ /* The Tx queue has any packets and is not being
+ transferred a packet from the host, start
+ transmitting. */
+ if (lp->tx_queue && lp->tx_queue_ready) {
outb(0x80 | lp->tx_queue, ioaddr + TX_START);
lp->tx_queue = 0;
lp->tx_queue_len = 0;
@@ -601,8 +669,6 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
mark_bh(NET_BH); /* Inform upper layers. */
} else {
lp->tx_started = 0;
- /* Turn on Tx interrupts off. */
- outb(0x00, ioaddr + TX_INTR);
dev->tbusy = 0;
mark_bh(NET_BH); /* Inform upper layers. */
}
@@ -698,7 +764,7 @@ net_rx(struct device *dev)
/* The inverse routine to net_open(). */
static int net_close(struct device *dev)
{
-/* struct net_local *lp = (struct net_local *)dev->priv;*/
+ struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
dev->tbusy = 1;
@@ -709,13 +775,11 @@ static int net_close(struct device *dev)
/* No statistic counters on the chip to update. */
-#if 0
- /* Disable the IRQ on boards where it is feasible. */
+ /* Disable the IRQ on boards of fmv18x where it is feasible. */
if (lp->jumpered) {
outb(0x00, ioaddr + IOCONFIG1);
free_irq(dev->irq, dev);
}
-#endif
/* Power-down the chip. Green, green, green! */
outb(0x00, ioaddr + CONFIG_1);
@@ -820,6 +884,10 @@ static struct device dev_at1700 = {
static int io = 0x260;
static int irq = 0;
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+MODULE_PARM(net_debug, "i");
+
int init_module(void)
{
if (io == 0)
@@ -836,12 +904,14 @@ int init_module(void)
void
cleanup_module(void)
{
+#ifdef CONFIG_MCA
struct net_local *lp = dev_at1700.priv;
- unregister_netdev(&dev_at1700);
if(lp->mca_slot)
{
mca_mark_as_unused(lp->mca_slot);
}
+#endif
+ unregister_netdev(&dev_at1700);
kfree(dev_at1700.priv);
dev_at1700.priv = NULL;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index c2e26819b..f9be725cd 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -5,6 +5,7 @@
* Copyright (C) 1998 Randy Gobbel.
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -59,7 +60,6 @@ struct bmac_data {
int rx_fill;
int rx_empty;
struct sk_buff *tx_bufs[N_TX_RING];
- char *tx_double[N_TX_RING]; /* yuck--double buffering */
int tx_fill;
int tx_empty;
unsigned char tx_fullup;
@@ -297,7 +297,7 @@ bmac_mif_read(struct device *dev, unsigned int addr)
val = bmac_mif_readbits(dev, 17);
bmwrite(dev, MIFCSR, 4);
MIFDELAY;
- printk(KERN_DEBUG "bmac_mif_read(%x) -> %x\n", addr, val);
+ /* printk(KERN_DEBUG "bmac_mif_read(%x) -> %x\n", addr, val); */
return val;
}
@@ -438,9 +438,11 @@ bmac_init_chip(struct device *dev)
bmac_mif_write(dev, 4, 0xa1);
bmac_mif_write(dev, 0, 0x1200);
}
+#if 0
/* XXX debugging */
bmac_mif_read(dev, 0);
bmac_mif_read(dev, 4);
+#endif
}
bmac_init_registers(dev);
return 1;
@@ -488,23 +490,15 @@ static inline void bmac_set_timeout(struct device *dev)
}
static void
-bmac_construct_xmt(struct sk_buff *skb, volatile struct dbdma_cmd *cp,
- char *doubleBuf)
+bmac_construct_xmt(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
{
- void *vaddr, *page_break;
+ void *vaddr;
unsigned long baddr;
unsigned long len;
len = skb->len;
vaddr = skb->data;
baddr = virt_to_bus(vaddr);
- page_break = round_page(vaddr);
- if (trunc_page(vaddr) != trunc_page(vaddr+len) &&
- (unsigned long)round_page(baddr) != virt_to_bus(page_break)) {
- baddr = virt_to_bus(doubleBuf);
- XXDEBUG(("bmac: double buffering, double=%#08x, skb->data=%#08x, len=%d\n", doubleBuf, skb->data, len));
- } else
- flush_page_to_ram((unsigned long)vaddr);
dbdma_setcmd(cp, (OUTPUT_LAST | INTR_ALWAYS | WAIT_IFCLR), len, baddr, 0);
}
@@ -530,17 +524,8 @@ bitrev(unsigned char b)
static int
bmac_init_tx_ring(struct bmac_data *bp)
{
- int i;
volatile struct dbdma_regs *td = bp->tx_dma;
- char *addr;
-
- if (!bp->tx_allocated) {
- /* zero out tx cmds, alloc space for double buffering */
- addr = (char *)kmalloc(ETHERMTU * N_TX_RING, GFP_DMA);
- if (addr == NULL) return 0;
- for (i = 0; i < N_TX_RING; i++, addr += ETHERMTU) bp->tx_double[i] = addr;
- bp->tx_allocated = 1;
- }
+
memset((char *)bp->tx_cmds, 0, (N_TX_RING+1) * sizeof(struct dbdma_cmd));
bp->tx_empty = 0;
@@ -615,7 +600,7 @@ static int bmac_transmit_packet(struct sk_buff *skb, struct device *dev)
dbdma_setcmd(&bp->tx_cmds[i], DBDMA_STOP, 0, 0, 0);
- bmac_construct_xmt(skb, &bp->tx_cmds[bp->tx_fill], bp->tx_double[bp->tx_fill]);
+ bmac_construct_xmt(skb, &bp->tx_cmds[bp->tx_fill]);
bp->tx_bufs[bp->tx_fill] = skb;
bp->tx_fill = i;
@@ -1177,6 +1162,8 @@ static int bmac_reset_and_enable(struct device *dev, int enable)
{
struct bmac_data *bp = dev->priv;
unsigned long flags;
+ struct sk_buff *skb;
+ unsigned char *data;
save_flags(flags); cli();
bp->reset_and_enabled = 0;
@@ -1187,16 +1174,17 @@ static int bmac_reset_and_enable(struct device *dev, int enable)
bmac_start_chip(dev);
bmwrite(dev, INTDISABLE, EnableNormal);
bp->reset_and_enabled = 1;
- /* { */
- /* unsigned char random_packet[100]; */
- /* unsigned int i; */
- /* struct sk_buff *skb = dev_alloc_skb(RX_BUFLEN+2); */
- /* unsigned char *data = skb_put(skb, sizeof(random_packet)); */
- /* XXDEBUG(("transmitting random packet\n")); */
- /* for (i = 0; i < sizeof(random_packet); i++) data[i] = i; */
- /* bmac_transmit_packet(skb, dev); */
- /* XXDEBUG(("done transmitting random packet\n")); */
- /* } */
+
+ /*
+ * It seems that the bmac can't receive until it's transmitted
+ * a packet. So we give it a dummy packet to transmit.
+ */
+ skb = dev_alloc_skb(ETHERMINPACKET);
+ data = skb_put(skb, ETHERMINPACKET);
+ memset(data, 0, ETHERMINPACKET);
+ memcpy(data, dev->dev_addr, 6);
+ memcpy(data+6, dev->dev_addr, 6);
+ bmac_transmit_packet(skb, dev);
}
restore_flags(flags);
return 1;
@@ -1241,8 +1229,13 @@ bmac_probe(struct device *dev)
dev->priv = kmalloc(PRIV_BYTES, GFP_KERNEL);
if (dev->priv == 0) return -ENOMEM;
}
+
+#ifdef MODULE
+ bmac_devs = dev;
+#endif
- dev->base_addr = bmacs->addrs[0].address;
+ dev->base_addr = (unsigned long)
+ ioremap(bmacs->addrs[0].address, bmacs->addrs[0].size);
dev->irq = bmacs->intrs[0].line;
bmwrite(dev, INTDISABLE, DisableAll);
@@ -1257,7 +1250,7 @@ bmac_probe(struct device *dev)
}
}
- printk(KERN_INFO "%s: BMAC at", dev->name);
+ printk(KERN_INFO "%s: BMAC%s at", dev->name, (is_bmac_plus? "+": ""));
rev = addr[0] == 0 && addr[1] == 0xA0;
for (j = 0; j < 6; ++j) {
dev->dev_addr[j] = rev? bitrev(addr[j]): addr[j];
@@ -1280,9 +1273,11 @@ bmac_probe(struct device *dev)
bp = (struct bmac_data *) dev->priv;
memset(bp, 0, sizeof(struct bmac_data));
- bp->tx_dma = (volatile struct dbdma_regs *) bmacs->addrs[1].address;
+ bp->tx_dma = (volatile struct dbdma_regs *)
+ ioremap(bmacs->addrs[1].address, bmacs->addrs[1].size);
bp->tx_dma_intr = bmacs->intrs[1].line;
- bp->rx_dma = (volatile struct dbdma_regs *) bmacs->addrs[2].address;
+ bp->rx_dma = (volatile struct dbdma_regs *)
+ ioremap(bmacs->addrs[2].address, bmacs->addrs[2].size);
bp->rx_dma_intr = bmacs->intrs[2].line;
bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
@@ -1370,8 +1365,6 @@ static int bmac_close(struct device *dev)
}
}
bp->rx_allocated = 0;
- XXDEBUG(("bmac: free doubles\n"));/*MEMORY LEAK BELOW!!! FIX!!! */
- if (bp->tx_double[0] != NULL) kfree(bp->tx_double[0]);
XXDEBUG(("bmac: free tx bufs\n"));
for (i = 0; i<N_TX_RING; i++) {
if (bp->tx_bufs[i] != NULL) {
@@ -1379,7 +1372,6 @@ static int bmac_close(struct device *dev)
bp->tx_bufs[i] = NULL;
}
}
- bp->tx_allocated = 0;
bp->reset_and_enabled = 0;
XXDEBUG(("bmac: all bufs freed\n"));
@@ -1539,3 +1531,32 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length, int dummy)
return len;
}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Randy Gobbel/Paul Mackerras");
+MODULE_DESCRIPTION("PowerMac BMAC ethernet driver.");
+
+int init_module(void)
+{
+ int res;
+
+ if(bmac_devs != NULL)
+ return -EBUSY;
+ res = bmac_probe(NULL);
+ return res;
+}
+void cleanup_module(void)
+{
+ struct bmac_data *bp = (struct bmac_data *) bmac_devs->priv;
+ unregister_netdev(bmac_devs);
+
+ free_irq(bmac_devs->irq, bmac_misc_intr);
+ free_irq(bp->tx_dma_intr, bmac_txdma_intr);
+ free_irq(bp->rx_dma_intr, bmac_rxdma_intr);
+
+ kfree(bmac_devs);
+ bmac_devs = NULL;
+}
+
+#endif
diff --git a/drivers/net/cops.h b/drivers/net/cops.h
index a064bc12b..69721566f 100644
--- a/drivers/net/cops.h
+++ b/drivers/net/cops.h
@@ -34,7 +34,7 @@
/* Same on both card types */
#define COPS_CLEAR_INT 1
-/* LAP response codes recieved from the cards. */
+/* LAP response codes received from the cards. */
#define LAP_INIT 1 /* Init cmd */
#define LAP_INIT_RSP 2 /* Init response */
#define LAP_WRITE 3 /* Write cmd */
diff --git a/drivers/net/cosa.c b/drivers/net/cosa.c
new file mode 100644
index 000000000..5c76aa0d4
--- /dev/null
+++ b/drivers/net/cosa.c
@@ -0,0 +1,1909 @@
+/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
+
+/*
+ * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ */
+
+/*
+ * The driver for the SRP and COSA synchronous serial cards.
+ *
+ * HARDWARE INFO
+ *
+ * Both cards are developed at the Institute of Computer Science,
+ * Masaryk University (http://www.ics.muni.cz/). The hardware is
+ * developed by Jiri Novotny <novotny@ics.muni.cz>. More information
+ * and the photo of both cards is available at
+ * http://www.kozakmartin.cz/cosa.html. The card documentation, firmwares
+ * and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/.
+ * For Linux-specific utilities, see below in the "Software info" section.
+ * If you want to order the card, contact Jiri Novotny.
+ *
+ * The SRP (serial port?, the Czech word "srp" means "sickle") card
+ * is a 2-port intelligent (with its own 8-bit CPU) synchronous serial card
+ * with V.24 interfaces up to 80kb/s each.
+ *
+ * The COSA (communication serial adapter?, the Czech word "kosa" means
+ * "scythe") is a next-generation sync/async board with two interfaces
+ * - currently any of V.24, X.21, V.35 and V.36 can be selected.
+ * It has a 16-bit SAB80166 CPU and can do up to 10 Mb/s per channel.
+ * The 8-channels version is in development.
+ *
+ * Both types have downloadable firmware and communicate via ISA DMA.
+ * COSA can be also a bus-mastering device.
+ *
+ * SOFTWARE INFO
+ *
+ * The homepage of the Linux driver is at http://www.fi.muni.cz/~kas/cosa/.
+ * The CVS tree of Linux driver can be viewed there, as well as the
+ * firmware binaries and user-space utilities for downloading the firmware
+ * into the card and setting up the card.
+ *
+ * The Linux driver (unlike the present *BSD drivers :-) can work even
+ * for the COSA and SRP in one computer and allows each channel to work
+ * in one of the three modes (character device, Cisco HDLC, Sync PPP).
+ *
+ * AUTHOR
+ *
+ * The Linux driver was written by Jan "Yenya" Kasprzak <kas@fi.muni.cz>.
+ *
+ * You can mail me bugfixes and even success reports. I am especially
+ * interested in the SMP and/or muliti-channel success/failure reports
+ * (I wonder if I did the locking properly :-).
+ *
+ * THE AUTHOR USED THE FOLLOWING SOURCES WHEN PROGRAMMING THE DRIVER
+ *
+ * The COSA/SRP NetBSD driver by Zdenek Salvet and Ivos Cernohlavek
+ * The skeleton.c by Donald Becker
+ * The SDL Riscom/N2 driver by Mike Natale
+ * The Comtrol Hostess SV11 driver by Alan Cox
+ * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
+ */
+
+/* ---------- Headers, macros, data structures ---------- */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+
+#undef COSA_SLOW_IO /* for testing purposes only */
+#undef REALLY_SLOW_IO
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+#include <asm/spinlock.h>
+
+#include "syncppp.h"
+#include "cosa.h"
+
+/* Maximum length of the identification string. */
+#define COSA_MAX_ID_STRING 128
+
+/* Maximum length of the channel name */
+#define COSA_MAX_NAME (sizeof("cosaXXXcXXX")+1)
+
+/* Per-channel data structure */
+
+struct channel_data {
+ int usage; /* Usage count; >0 for chrdev, -1 for netdev */
+ int num; /* Number of the channel */
+ struct cosa_data *cosa; /* Pointer to the per-card structure */
+ int txsize; /* Size of transmitted data */
+ char *txbuf; /* Transmit buffer */
+ char name[COSA_MAX_NAME]; /* channel name */
+
+ /* The HW layer interface */
+ /* routine called from the RX interrupt */
+ char *(*setup_rx)(struct channel_data *channel, int size);
+ /* routine called when the RX is done (from the EOT interrupt) */
+ int (*rx_done)(struct channel_data *channel);
+ /* routine called when the TX is done (from the EOT interrupt) */
+ int (*tx_done)(struct channel_data *channel, int size);
+
+ /* Character device parts */
+ struct semaphore rsem, wsem;
+ char *rxdata;
+ int rxsize;
+ struct wait_queue *txwaitq, *rxwaitq;
+ int tx_status, rx_status;
+
+ /* SPPP/HDLC device parts */
+ struct ppp_device pppdev;
+ struct sk_buff *rx_skb, *tx_skb;
+ struct net_device_stats stats;
+};
+
+struct cosa_data {
+ int num; /* Card number */
+ char name[COSA_MAX_NAME]; /* Card name - e.g "cosa0" */
+ unsigned int datareg, statusreg; /* I/O ports */
+ unsigned short irq, dma; /* IRQ and DMA number */
+ unsigned short startaddr; /* Firmware start address */
+ int nchannels; /* # of channels on this card */
+ int driver_status; /* For communicating with firware */
+ int firmware_status; /* Downloaded, reseted, etc. */
+ int rxbitmap, txbitmap; /* Bitmap of channels who are willing to send/receive data */
+ int rxtx; /* RX or TX in progress? */
+ int usage; /* usage count */
+ int txchan, txsize, rxsize;
+ struct channel_data *rxchan;
+ char *bouncebuf;
+ char *txbuf, *rxbuf;
+ struct channel_data *chan;
+ spinlock_t lock; /* For exclusive operations on this structure */
+ char id_string[COSA_MAX_ID_STRING]; /* ROM monitor ID string */
+ char *type; /* card type */
+};
+
+/*
+ * Define this if you want all the possible ports to be autoprobed.
+ * It is here but it probably is not a good idea to use this.
+ */
+/* #define COSA_ISA_AUTOPROBE 1 */
+
+/*
+ * Character device major number. 117 was allocated for us.
+ * The value of 0 means to allocate a first free one.
+ */
+static int cosa_major = 117;
+
+/*
+ * Encoding of the minor numbers:
+ * The lowest CARD_MINOR_BITS bits means the channel on the single card,
+ * the highest bits means the card number.
+ */
+#define CARD_MINOR_BITS 4 /* How many bits in minor number are reserved
+ * for the single card */
+/*
+ * The following depends on CARD_MINOR_BITS. Unfortunately, the "MODULE_STRING"
+ * macro doesn't like anything other than the raw number as an argument :-(
+ */
+#define MAX_CARDS 16
+/* #define MAX_CARDS (1 << (8-CARD_MINOR_BITS)) */
+
+#define DRIVER_RX_READY 0x0001
+#define DRIVER_TX_READY 0x0002
+#define DRIVER_TXMAP_SHIFT 2
+#define DRIVER_TXMAP_MASK 0x0c /* FIXME: 0xfc for 8-channel version */
+
+/*
+ * for cosa->rxtx - indicates whether either transmit or receive is
+ * in progress. These values are mean number of the bit.
+ */
+#define TXBIT 0
+#define RXBIT 1
+#define IRQBIT 2
+
+#define COSA_MTU 2000 /* FIXME: I don't know this exactly */
+
+#undef DEBUG_DATA 1 /* Dump the data read or written to the channel */
+#undef DEBUG_IRQS 1 /* Print the message when the IRQ is received */
+#undef DEBUG_IO 1 /* Dump the I/O traffic */
+
+/* Maybe the following should be allocated dynamically */
+static struct cosa_data cosa_cards[MAX_CARDS];
+static int nr_cards = 0;
+
+#ifdef COSA_ISA_AUTOPROBE
+static int io[MAX_CARDS+1] = { 0x220, 0x228, 0x210, 0x218, 0, };
+/* NOTE: DMA is not autoprobed!!! */
+static int dma[MAX_CARDS+1] = { 1, 7, 1, 7, 1, 7, 1, 7, 0, };
+#else
+int io[MAX_CARDS+1] = { 0, };
+int dma[MAX_CARDS+1] = { 0, };
+#endif
+/* IRQ can be safely autoprobed */
+static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
+
+#ifdef MODULE
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM_DESC(io, "The I/O bases of the COSA or SRP cards");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM_DESC(irq, "The IRQ lines of the COSA or SRP cards");
+MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM_DESC(dma, "The DMA channels of the COSA or SRP cards");
+
+MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, <kas@fi.muni.cz>");
+MODULE_DESCRIPTION("Modular driver for the COSA or SRP synchronous card");
+#endif
+
+/* I use this mainly for testing purposes */
+#ifdef COSA_SLOW_IO
+#define cosa_outb outb_p
+#define cosa_outw outw_p
+#define cosa_inb inb_p
+#define cosa_inw inw_p
+#else
+#define cosa_outb outb
+#define cosa_outw outw
+#define cosa_inb inb
+#define cosa_inw inw
+#endif
+
+#define is_8bit(cosa) (!(cosa->datareg & 0x08))
+
+#define cosa_getstatus(cosa) (cosa_inb(cosa->statusreg))
+#define cosa_putstatus(cosa, stat) (cosa_outb(stat, cosa->statusreg))
+#define cosa_getdata16(cosa) (cosa_inw(cosa->datareg))
+#define cosa_getdata8(cosa) (cosa_inb(cosa->datareg))
+#define cosa_putdata16(cosa, dt) (cosa_outw(dt, cosa->datareg))
+#define cosa_putdata8(cosa, dt) (cosa_outb(dt, cosa->datareg))
+
+/* Initialization stuff */
+static int cosa_probe(int ioaddr, int irq, int dma);
+
+/* HW interface */
+static void cosa_enable_rx(struct channel_data *chan);
+static void cosa_disable_rx(struct channel_data *chan);
+static int cosa_start_tx(struct channel_data *channel, char *buf, int size);
+static void cosa_kick(struct cosa_data *cosa);
+static int cosa_dma_able(struct channel_data *chan, char *buf, int data);
+
+/* SPPP/HDLC stuff */
+static void sppp_channel_init(struct channel_data *chan);
+static void sppp_channel_delete(struct channel_data *chan);
+static int cosa_sppp_open(struct device *d);
+static int cosa_sppp_close(struct device *d);
+static int cosa_sppp_tx(struct sk_buff *skb, struct device *d);
+static char *sppp_setup_rx(struct channel_data *channel, int size);
+static int sppp_rx_done(struct channel_data *channel);
+static int sppp_tx_done(struct channel_data *channel, int size);
+static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static struct net_device_stats *cosa_net_stats(struct device *dev);
+
+/* Character device */
+static void chardev_channel_init(struct channel_data *chan);
+static char *chrdev_setup_rx(struct channel_data *channel, int size);
+static int chrdev_rx_done(struct channel_data *channel);
+static int chrdev_tx_done(struct channel_data *channel, int size);
+static long long cosa_lseek(struct file *file,
+ long long offset, int origin);
+static ssize_t cosa_read(struct file *file,
+ char *buf, size_t count, loff_t *ppos);
+static ssize_t cosa_write(struct file *file,
+ const char *buf, size_t count, loff_t *ppos);
+static unsigned int cosa_poll(struct file *file, poll_table *poll);
+static int cosa_open(struct inode *inode, struct file *file);
+static int cosa_release(struct inode *inode, struct file *file);
+static int cosa_chardev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg);
+#ifdef COSA_FASYNC_WORKING
+static int cosa_fasync(struct inode *inode, struct file *file, int on);
+#endif
+
+static struct file_operations cosa_fops = {
+ cosa_lseek,
+ cosa_read,
+ cosa_write,
+ NULL, /* readdir */
+ cosa_poll,
+ cosa_chardev_ioctl,
+ NULL, /* mmap */
+ cosa_open,
+ NULL, /* flush */
+ cosa_release,
+ NULL, /* fsync */
+#ifdef COSA_FASYNC_WORKING
+ cosa_fasync,
+#else
+ NULL,
+#endif
+ NULL, /* check media change */
+ NULL, /* revalidate */
+ NULL /* lock */
+};
+
+/* Ioctls */
+static int cosa_start(struct cosa_data *cosa, int address);
+static int cosa_reset(struct cosa_data *cosa);
+static int cosa_download(struct cosa_data *cosa, struct cosa_download *d);
+static int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d);
+
+/* COSA/SRP ROM monitor */
+static int download(struct cosa_data *cosa, char *data, int addr, int len);
+static int startmicrocode(struct cosa_data *cosa, int address);
+static int readmem(struct cosa_data *cosa, char *data, int addr, int len);
+static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
+
+/* Auxilliary functions */
+static int get_wait_data(struct cosa_data *cosa);
+static int put_wait_data(struct cosa_data *cosa, int data);
+static int puthexnumber(struct cosa_data *cosa, int number);
+static void put_driver_status_common(struct cosa_data *cosa, int nolock);
+#define put_driver_status(x) put_driver_status_common((x), 0)
+#define put_driver_status_nolock(x) put_driver_status_common((x), 1)
+
+/* Interrupt handling */
+static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
+
+/* I/O ops debugging */
+#ifdef DEBUG_IO
+static void debug_data_in(struct cosa_data *cosa, int data);
+static void debug_data_out(struct cosa_data *cosa, int data);
+static void debug_data_cmd(struct cosa_data *cosa, int data);
+static void debug_status_in(struct cosa_data *cosa, int status);
+static void debug_status_out(struct cosa_data *cosa, int status);
+#endif
+
+
+/* ---------- Initialization stuff ---------- */
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(static int cosa_init(void))
+#endif
+{
+ int i;
+ printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
+#ifdef __SMP__
+ printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
+#endif
+ if (cosa_major > 0) {
+ if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
+ printk(KERN_WARNING "cosa: unable to get major %d\n",
+ cosa_major);
+ return -EIO;
+ }
+ } else {
+ if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
+ printk(KERN_WARNING "cosa: unable to register chardev\n");
+ return -EIO;
+ }
+ }
+ for (i=0; i<MAX_CARDS; i++)
+ cosa_cards[i].num = -1;
+ for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
+ cosa_probe(io[i], irq[i], dma[i]);
+ if (!nr_cards) {
+ printk(KERN_WARNING "cosa: no devices found.\n");
+ unregister_chrdev(cosa_major, "cosa");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+#ifdef MODULE
+void cleanup_module (void)
+{
+ struct cosa_data *cosa;
+ printk(KERN_INFO "Unloading the cosa module\n");
+
+ for (cosa=cosa_cards; nr_cards--; cosa++) {
+ int i;
+ /* Clean up the per-channel data */
+ for (i=0; i<cosa->nchannels; i++) {
+ /* Chardev driver has no alloc'd per-channel data */
+ sppp_channel_delete(cosa->chan+i);
+ }
+ /* Clean up the per-card data */
+ kfree(cosa->chan);
+ kfree(cosa->bouncebuf);
+ free_irq(cosa->irq, cosa);
+ free_dma(cosa->dma);
+ release_region(cosa->datareg,is_8bit(cosa)?2:4);
+ }
+ unregister_chrdev(cosa_major, "cosa");
+}
+#endif
+
+/*
+ * This function should register all the net devices needed for the
+ * single channel.
+ */
+static __inline__ void channel_init(struct channel_data *chan)
+{
+ sprintf(chan->name, "cosa%dc%d", chan->cosa->num, chan->num);
+
+ /* Initialize the chardev data structures */
+ chardev_channel_init(chan);
+
+ /* Register the sppp interface */
+ sppp_channel_init(chan);
+}
+
+static int cosa_probe(int base, int irq, int dma)
+{
+ struct cosa_data *cosa = cosa_cards+nr_cards;
+ int i;
+
+ memset(cosa, 0, sizeof(struct cosa_data));
+
+ /* Checking validity of parameters: */
+ /* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
+ if ((irq >= 0 && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
+ printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq);
+ return -1;
+ }
+ /* I/O address should be between 0x100 and 0x3ff and should be
+ * multiple of 8. */
+ if (base < 0x100 || base > 0x3ff || base & 0x7) {
+ printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n",
+ base);
+ return -1;
+ }
+ /* DMA should be 0,1 or 3-7 */
+ if (dma < 0 || dma == 4 || dma > 7) {
+ printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma);
+ return -1;
+ }
+ /* and finally, on 16-bit COSA DMA should be 4-7 and
+ * I/O base should not be multiple of 0x10 */
+ if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
+ printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch"
+ " (base=0x%x, dma=%d)\n", base, dma);
+ return -1;
+ }
+
+ cosa->dma = dma;
+ cosa->datareg = base;
+ cosa->statusreg = is_8bit(cosa)?base+1:base+2;
+ spin_lock_init(&cosa->lock);
+
+ if (check_region(base, is_8bit(cosa)?2:4))
+ return -1;
+
+ if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
+ printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base);
+ return -1;
+ }
+
+ /* Test the validity of identification string */
+ if (!strncmp(cosa->id_string, "SRP", 3))
+ cosa->type = "srp";
+ else if (!strncmp(cosa->id_string, "COSA", 4))
+ cosa->type = is_8bit(cosa)? "cosa8": "cosa16";
+ else {
+/* Print a warning only if we are not autoprobing */
+#ifndef COSA_ISA_AUTOPROBE
+ printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n",
+ base);
+#endif
+ return -1;
+ }
+
+ /* Now do IRQ autoprobe */
+ if (irq < 0) {
+ unsigned long irqs;
+/* printk(KERN_INFO "IRQ autoprobe\n"); */
+ sti();
+ irqs = probe_irq_on();
+ /*
+ * Enable interrupt on tx buffer empty (it sure is)
+ * really sure ?
+ * FIXME: When this code is not used as module, we should
+ * probably call udelay() instead of the interruptible sleep.
+ */
+ current->state = TASK_INTERRUPTIBLE;
+ cosa_putstatus(cosa, SR_TX_INT_ENA);
+ schedule_timeout(30);
+ current->state = TASK_RUNNING;
+ irq = probe_irq_off(irqs);
+ /* Disable all IRQs from the card */
+ cosa_putstatus(cosa, 0);
+ /* Empty the received data register */
+ cosa_getdata8(cosa);
+
+ if (irq < 0) {
+ printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",
+ irq, cosa->datareg);
+ return -1;
+ }
+ if (irq == 0) {
+ printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",
+ cosa->datareg);
+ /* return -1; */
+ }
+ }
+
+ cosa->irq = irq;
+ cosa->num = nr_cards;
+ cosa->usage = 0;
+ cosa->nchannels = 2; /* FIXME: how to determine this? */
+
+ request_region(base, is_8bit(cosa)?2:4, cosa->type);
+ if (request_irq(cosa->irq, cosa_interrupt, 0, cosa->type, cosa))
+ goto bad1;
+ if (request_dma(cosa->dma, cosa->type)) {
+ free_irq(cosa->irq, cosa);
+bad1: release_region(cosa->datareg,is_8bit(cosa)?2:4);
+ printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
+ cosa->num);
+ return -1;
+ }
+
+ cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL|GFP_DMA);
+ sprintf(cosa->name, "cosa%d", cosa->num);
+
+ /* Initialize the per-channel data */
+ cosa->chan = kmalloc(sizeof(struct channel_data)*cosa->nchannels,
+ GFP_KERNEL);
+ memset(cosa->chan, 0, sizeof(struct channel_data)*cosa->nchannels);
+ for (i=0; i<cosa->nchannels; i++) {
+ cosa->chan[i].cosa = cosa;
+ cosa->chan[i].num = i;
+ channel_init(cosa->chan+i);
+ }
+
+ printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
+ cosa->num, cosa->id_string, cosa->type,
+ cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
+
+ return nr_cards++;
+}
+
+
+/*---------- SPPP/HDLC netdevice ---------- */
+
+static void sppp_channel_init(struct channel_data *chan)
+{
+ struct device *d;
+ sppp_attach(&chan->pppdev);
+ d=&chan->pppdev.dev;
+ d->name = chan->name;
+ d->base_addr = chan->cosa->datareg;
+ d->irq = chan->cosa->irq;
+ d->dma = chan->cosa->dma;
+ d->priv = chan;
+ d->init = NULL;
+ d->open = cosa_sppp_open;
+ d->stop = cosa_sppp_close;
+ d->hard_start_xmit = cosa_sppp_tx;
+ d->do_ioctl = cosa_sppp_ioctl;
+ d->get_stats = cosa_net_stats;
+ dev_init_buffers(d);
+ if (register_netdev(d) == -1) {
+ printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
+ sppp_detach(&chan->pppdev.dev);
+ return;
+ }
+}
+
+static void sppp_channel_delete(struct channel_data *chan)
+{
+ sppp_detach(&chan->pppdev.dev);
+ unregister_netdev(&chan->pppdev.dev);
+}
+
+
+static int cosa_sppp_open(struct device *d)
+{
+ struct channel_data *chan = d->priv;
+ int err, flags;
+
+ spin_lock_irqsave(&chan->cosa->lock, flags);
+ if (chan->usage != 0) {
+ printk(KERN_WARNING "%s: sppp_open called with usage count %d\n",
+ chan->name, chan->usage);
+ return -EBUSY;
+ }
+ chan->setup_rx = sppp_setup_rx;
+ chan->tx_done = sppp_tx_done;
+ chan->rx_done = sppp_rx_done;
+ chan->usage=-1;
+ chan->cosa->usage++;
+ MOD_INC_USE_COUNT;
+ spin_unlock_irqrestore(&chan->cosa->lock, flags);
+
+ err = sppp_open(d);
+ if (err) {
+ spin_lock_irqsave(&chan->cosa->lock, flags);
+ chan->usage=0;
+ chan->cosa->usage--;
+ MOD_DEC_USE_COUNT;
+
+ spin_unlock_irqrestore(&chan->cosa->lock, flags);
+ return err;
+ }
+
+ d->tbusy = 0;
+ cosa_enable_rx(chan);
+ return 0;
+}
+
+static int cosa_sppp_tx(struct sk_buff *skb, struct device *dev)
+{
+ struct channel_data *chan = dev->priv;
+
+ if (dev->tbusy) {
+ if (time_before(jiffies, dev->trans_start+2*HZ))
+ return 1; /* Two seconds timeout */
+ cosa_kick(chan->cosa);
+ chan->stats.tx_errors++;
+ chan->stats.tx_aborted_errors++;
+ if (chan->tx_skb) {
+ dev_kfree_skb(chan->tx_skb);
+ chan->tx_skb = 0;
+ }
+ dev->tbusy = 0;
+ }
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+ return 1;
+ }
+
+ chan->tx_skb = skb;
+ dev->trans_start = jiffies;
+ cosa_start_tx(chan, skb->data, skb->len);
+ return 0;
+}
+
+static int cosa_sppp_close(struct device *d)
+{
+ struct channel_data *chan = d->priv;
+ int flags;
+
+ sppp_close(d);
+ d->tbusy = 1;
+ cosa_disable_rx(chan);
+ spin_lock_irqsave(&chan->cosa->lock, flags);
+ chan->usage=0;
+ chan->cosa->usage--;
+ MOD_DEC_USE_COUNT;
+ spin_unlock_irqrestore(&chan->cosa->lock, flags);
+ return 0;
+}
+
+static char *sppp_setup_rx(struct channel_data *chan, int size)
+{
+ /*
+ * We can safely fall back to non-dma-able memory, because we have
+ * the cosa->bouncebuf pre-allocated.
+ */
+ if (chan->rx_skb)
+ kfree_skb(chan->rx_skb);
+ chan->rx_skb = dev_alloc_skb(size);
+ if (chan->rx_skb == NULL) {
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
+ chan->name);
+ chan->stats.rx_dropped++;
+ return NULL;
+ }
+ chan->pppdev.dev.trans_start = jiffies;
+ return skb_put(chan->rx_skb, size);
+}
+
+static int sppp_rx_done(struct channel_data *chan)
+{
+ if (!chan->rx_skb) {
+ printk(KERN_WARNING "%s: rx_done with empty skb!\n",
+ chan->name);
+ chan->stats.rx_errors++;
+ chan->stats.rx_frame_errors++;
+ return 0;
+ }
+ chan->rx_skb->protocol = htons(ETH_P_WAN_PPP);
+ chan->rx_skb->dev = &chan->pppdev.dev;
+ chan->rx_skb->mac.raw = chan->rx_skb->data;
+ chan->stats.rx_packets++;
+ chan->stats.rx_bytes += chan->cosa->rxsize;
+ netif_rx(chan->rx_skb);
+ chan->rx_skb = 0;
+ chan->pppdev.dev.trans_start = jiffies;
+ return 0;
+}
+
+/* ARGSUSED */
+static int sppp_tx_done(struct channel_data *chan, int size)
+{
+ if (!chan->tx_skb) {
+ printk(KERN_WARNING "%s: tx_done with empty skb!\n",
+ chan->name);
+ chan->stats.tx_errors++;
+ chan->stats.tx_aborted_errors++;
+ return 1;
+ }
+ dev_kfree_skb(chan->tx_skb);
+ chan->tx_skb = 0;
+ chan->stats.tx_packets++;
+ chan->stats.tx_bytes += size;
+ chan->pppdev.dev.tbusy = 0;
+ mark_bh(NET_BH);
+ return 1;
+}
+
+static struct net_device_stats *cosa_net_stats(struct device *dev)
+{
+ struct channel_data *chan = dev->priv;
+ return &chan->stats;
+}
+
+
+/*---------- Character device ---------- */
+
+static void chardev_channel_init(struct channel_data *chan)
+{
+ chan->rsem = MUTEX;
+ chan->wsem = MUTEX;
+}
+
+static long long cosa_lseek(struct file * file,
+ long long offset, int origin)
+{
+ return -ESPIPE;
+}
+
+static ssize_t cosa_read(struct file *file,
+ char *buf, size_t count, loff_t *ppos)
+{
+ struct wait_queue wait = { current, NULL };
+ int flags;
+ struct channel_data *chan = (struct channel_data *)file->private_data;
+ struct cosa_data *cosa = chan->cosa;
+ char *kbuf;
+
+ if (down_interruptible(&chan->rsem))
+ return -ERESTARTSYS;
+
+ if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
+ printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+ up(&chan->rsem);
+ return -ENOMEM;
+ }
+
+ chan->rx_status = 0;
+ cosa_enable_rx(chan);
+ spin_lock_irqsave(&cosa->lock, flags);
+ add_wait_queue(&chan->rxwaitq, &wait);
+ while(!chan->rx_status) {
+ current->state = TASK_INTERRUPTIBLE;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ schedule();
+ spin_lock_irqsave(&cosa->lock, flags);
+ if (signal_pending(current) && chan->rx_status == 0) {
+ chan->rx_status = 1;
+ remove_wait_queue(&chan->rxwaitq, &wait);
+ current->state = TASK_RUNNING;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ up(&chan->rsem);
+ return -ERESTARTSYS;
+ }
+ }
+ remove_wait_queue(&chan->rxwaitq, &wait);
+ current->state = TASK_RUNNING;
+ kbuf = chan->rxdata;
+ count = chan->rxsize;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ up(&chan->rsem);
+
+ if (copy_to_user(buf, kbuf, count)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ kfree(kbuf);
+ return count;
+}
+
+static char *chrdev_setup_rx(struct channel_data *chan, int size)
+{
+ /* Expect size <= COSA_MTU */
+ chan->rxsize = size;
+ return chan->rxdata;
+}
+
+static int chrdev_rx_done(struct channel_data *chan)
+{
+ if (chan->rx_status) { /* Reader has died */
+ kfree(chan->rxdata);
+ up(&chan->wsem);
+ }
+ chan->rx_status = 1;
+ wake_up_interruptible(&chan->rxwaitq);
+ return 1;
+}
+
+
+static ssize_t cosa_write(struct file *file,
+ const char *buf, size_t count, loff_t *ppos)
+{
+ struct channel_data *chan = (struct channel_data *)file->private_data;
+ struct wait_queue wait = { current, NULL };
+ struct cosa_data *cosa = chan->cosa;
+ unsigned int flags;
+ char *kbuf;
+
+ if (down_interruptible(&chan->wsem))
+ return -ERESTARTSYS;
+
+ if (count > COSA_MTU)
+ count = COSA_MTU;
+
+ /* Allocate the buffer */
+ if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {
+ printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",
+ cosa->name);
+ up(&chan->wsem);
+ return -ENOMEM;
+ }
+ if (copy_from_user(kbuf, buf, count)) {
+ up(&chan->wsem);
+ kfree(kbuf);
+ return -EFAULT;
+ }
+ chan->tx_status=0;
+ cosa_start_tx(chan, kbuf, count);
+
+ spin_lock_irqsave(&cosa->lock, flags);
+ add_wait_queue(&chan->txwaitq, &wait);
+ while(!chan->tx_status) {
+ current->state = TASK_INTERRUPTIBLE;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ schedule();
+ spin_lock_irqsave(&cosa->lock, flags);
+ if (signal_pending(current) && chan->tx_status == 0) {
+ chan->tx_status = 1;
+ remove_wait_queue(&chan->txwaitq, &wait);
+ current->state = TASK_RUNNING;
+ chan->tx_status = 1;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return -ERESTARTSYS;
+ }
+ }
+ remove_wait_queue(&chan->txwaitq, &wait);
+ current->state = TASK_RUNNING;
+ up(&chan->wsem);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ kfree(kbuf);
+ return count;
+}
+
+static int chrdev_tx_done(struct channel_data *chan, int size)
+{
+ if (chan->tx_status) { /* Writer was interrupted */
+ kfree(chan->txbuf);
+ up(&chan->wsem);
+ }
+ chan->tx_status = 1;
+ wake_up_interruptible(&chan->txwaitq);
+ return 1;
+}
+
+static unsigned int cosa_poll(struct file *file, poll_table *poll)
+{
+ printk(KERN_INFO "cosa_poll is here\n");
+ return 0;
+}
+
+static int cosa_open(struct inode *inode, struct file *file)
+{
+ struct cosa_data *cosa;
+ struct channel_data *chan;
+ unsigned long flags;
+ int n;
+
+ if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
+ >= nr_cards)
+ return -ENODEV;
+ cosa = cosa_cards+n;
+
+ if ((n=MINOR(file->f_dentry->d_inode->i_rdev)
+ & ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
+ return -ENODEV;
+ chan = cosa->chan + n;
+
+ file->private_data = chan;
+
+ spin_lock_irqsave(&cosa->lock, flags);
+
+ if (chan->usage < 0) { /* in netdev mode */
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return -EBUSY;
+ }
+ cosa->usage++;
+ chan->usage++;
+
+ chan->tx_done = chrdev_tx_done;
+ chan->setup_rx = chrdev_setup_rx;
+ chan->rx_done = chrdev_rx_done;
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return 0;
+}
+
+static int cosa_release(struct inode *inode, struct file *file)
+{
+ struct channel_data *channel = (struct channel_data *)file->private_data;
+ struct cosa_data *cosa = channel->cosa;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cosa->lock, flags);
+ cosa->usage--;
+ channel->usage--;
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return 0;
+}
+
+#ifdef COSA_FASYNC_WORKING
+static struct fasync_struct *fasync[256] = { NULL, };
+
+/* To be done ... */
+static int cosa_fasync(struct inode *inode, struct file *file, int on)
+{
+ int port = MINOR(inode->i_rdev);
+ int rv = fasync_helper(inode, file, on, &fasync[port]);
+ return rv < 0 ? rv : 0;
+}
+#endif
+
+
+/* ---------- Ioctls ---------- */
+
+/*
+ * Ioctl subroutines can safely be made inline, because they are called
+ * only from cosa_ioctl().
+ */
+static inline int cosa_reset(struct cosa_data *cosa)
+{
+ char idstring[COSA_MAX_ID_STRING];
+ if (cosa->usage > 1)
+ printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ cosa->num, cosa->usage);
+ if (cosa_reset_and_read_id(cosa, idstring) < 0) {
+ printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);
+ return -EIO;
+ }
+ printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,
+ idstring);
+ return 0;
+}
+
+/* High-level function to download data into COSA memory. Calls download() */
+static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d)
+{
+ int i;
+ int addr, len;
+ char *code;
+
+ if (cosa->usage > 1)
+ printk(KERN_INFO "cosa%d: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ cosa->num, cosa->usage);
+#if 0
+ if (cosa->status != CARD_STATUS_RESETED && cosa->status != CARD_STATUS_DOWNLOADED) {
+ printk(KERN_NOTICE "cosa%d: reset the card first (status %d).\n",
+ cosa->num, cosa->status);
+ return -EPERM;
+ }
+#endif
+ get_user_ret(addr, &(d->addr), -EFAULT);
+ get_user_ret(len, &(d->len), -EFAULT);
+ get_user_ret(code, &(d->code), -EFAULT);
+
+ if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE)
+ return -EINVAL;
+ if (d->len < 0 || d->len > COSA_MAX_FIRMWARE_SIZE)
+ return -EINVAL;
+
+ if ((i=download(cosa, d->code, len, addr)) < 0) {
+ printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
+ cosa->num, i);
+ return -EIO;
+ }
+ printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
+ cosa->num, len, addr);
+ return 0;
+}
+
+/* High-level function to read COSA memory. Calls readmem() */
+static inline int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d)
+{
+ int i;
+ int addr, len;
+ char *code;
+
+ if (cosa->usage > 1)
+ printk(KERN_INFO "cosa%d: WARNING: readmem requested with "
+ "cosa->usage > 1 (%d). Odd things may happen.\n",
+ cosa->num, cosa->usage);
+#if 0
+ if (cosa->status != CARD_STATUS_RESETED &&
+ cosa->status != CARD_STATUS_DOWNLOADED) {
+ printk(KERN_NOTICE "cosa%d: reset the card first (status %d).\n",
+ cosa->num, cosa->status);
+ return -EPERM;
+ }
+#endif
+ get_user_ret(addr, &(d->addr), -EFAULT);
+ get_user_ret(len, &(d->len), -EFAULT);
+ get_user_ret(code, &(d->code), -EFAULT);
+
+ if ((i=readmem(cosa, d->code, len, addr)) < 0) {
+ printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n",
+ cosa->num, i);
+ return -EIO;
+ }
+ printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
+ cosa->num, len, addr);
+ return 0;
+}
+
+/* High-level function to start microcode. Calls startmicrocode(). */
+static inline int cosa_start(struct cosa_data *cosa, int address)
+{
+ int i;
+
+ if (cosa->usage > 1)
+ printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+ cosa->num, cosa->usage);
+#if 0
+ if (cosa->status != CARD_STATUS_DOWNLOADED) {
+ printk(KERN_NOTICE "cosa%d: download the microcode first (status %d).\n",
+ cosa->num, cosa->status);
+ return -EPERM;
+ }
+#endif
+ if ((i=startmicrocode(cosa, address)) < 0) {
+ printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n",
+ cosa->num, address, i);
+ return -EIO;
+ }
+ printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n",
+ cosa->num, address);
+ cosa->startaddr = address;
+ return 0;
+}
+
+/* Buffer of size at least COSA_MAX_ID_STRING is expected */
+static inline int cosa_getidstr(struct cosa_data *cosa, char *string)
+{
+ int l = strlen(cosa->id_string)+1;
+ copy_to_user_ret(string, cosa->id_string, l, -EFAULT);
+ return l;
+}
+
+/* Buffer of size at least COSA_MAX_ID_STRING is expected */
+static inline int cosa_gettype(struct cosa_data *cosa, char *string)
+{
+ int l = strlen(cosa->type)+1;
+ copy_to_user_ret(string, cosa->type, l, -EFAULT);
+ return l;
+}
+
+static int cosa_ioctl_common(struct cosa_data *cosa,
+ struct channel_data *channel, unsigned int cmd, unsigned long arg)
+{
+ switch(cmd) {
+ case COSAIORSET: /* Reset the device */
+ if (!suser())
+ return -EACCES;
+ return cosa_reset(cosa);
+ case COSAIOSTRT: /* Start the firmware */
+ if (!suser())
+ return -EACCES;
+ return cosa_start(cosa, arg);
+ case COSAIODOWNLD: /* Download the firmware */
+ if (!suser())
+ return -EACCES;
+ return cosa_download(cosa, (struct cosa_download *)arg);
+ case COSAIORMEM:
+ if (!suser())
+ return -EACCES;
+ return cosa_readmem(cosa, (struct cosa_download *)arg);
+ case COSAIORTYPE:
+ return cosa_gettype(cosa, (char *)arg);
+ case COSAIORIDSTR:
+ return cosa_getidstr(cosa, (char *)arg);
+/*
+ * These two are _very_ugly_hack_(tm). Don't even look at this.
+ * Implementing this saved me few reboots after some process segfaulted
+ * inside this module.
+ */
+#ifdef MODULE
+#if 0
+ case COSAIOMINC:
+ MOD_INC_USE_COUNT;
+ return 0;
+ case COSAIOMDEC:
+ MOD_DEC_USE_COUNT;
+ return 0;
+#endif
+#endif
+ case COSAIONRCARDS:
+ return nr_cards;
+ case COSAIONRCHANS:
+ return cosa->nchannels;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr,
+ int cmd)
+{
+ int rv;
+ struct channel_data *chan = (struct channel_data *)dev->priv;
+ rv = cosa_ioctl_common(chan->cosa, chan, cmd, (int)ifr->ifr_data);
+ if (rv == -ENOIOCTLCMD) {
+ return sppp_do_ioctl(dev, ifr, cmd);
+ }
+ return rv;
+}
+
+static int cosa_chardev_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct channel_data *channel = (struct channel_data *)file->private_data;
+ struct cosa_data *cosa = channel->cosa;
+ return cosa_ioctl_common(cosa, channel, cmd, arg);
+}
+
+
+/*---------- HW layer interface ---------- */
+
+/*
+ * The higher layer can bind itself to the HW layer by setting the callbacks
+ * in the channel_data structure and by using these routines.
+ */
+static void cosa_enable_rx(struct channel_data *chan)
+{
+ struct cosa_data *cosa = chan->cosa;
+
+ if (!test_and_set_bit(chan->num, &cosa->rxbitmap))
+ put_driver_status(cosa);
+}
+
+static void cosa_disable_rx(struct channel_data *chan)
+{
+ struct cosa_data *cosa = chan->cosa;
+
+ if (test_and_clear_bit(chan->num, &cosa->rxbitmap))
+ put_driver_status(cosa);
+}
+
+/*
+ * FIXME: This routine probably should check for cosa_start_tx() called when
+ * the previous transmit is still unfinished. In this case the non-zero
+ * return value should indicate to the caller that the queuing(sp?) up
+ * the transmit has failed.
+ */
+static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
+{
+ struct cosa_data *cosa = chan->cosa;
+ int flags;
+#ifdef DEBUG_DATA
+ int i;
+
+ printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num,
+ chan->num, len);
+ for (i=0; i<len; i++)
+ printk(" %02x", buf[i]&0xff);
+ printk("\n");
+#endif
+ spin_lock_irqsave(&cosa->lock, flags);
+ chan->txbuf = buf;
+ chan->txsize = len;
+ if (len > COSA_MTU)
+ chan->txsize = COSA_MTU;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+
+ /* Tell the firmware we are ready */
+ set_bit(chan->num, &cosa->txbitmap);
+ put_driver_status(cosa);
+
+ return 0;
+}
+
+static void put_driver_status_common(struct cosa_data *cosa, int nolock)
+{
+ unsigned flags=0;
+ int status;
+
+ if (!nolock)
+ spin_lock_irqsave(&cosa->lock, flags);
+
+ status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
+ | (cosa->txbitmap ? DRIVER_TX_READY : 0)
+ | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
+ &DRIVER_TXMAP_MASK : 0);
+ if (!cosa->rxtx || nolock) {
+#ifdef DEBUG_IO
+ debug_data_cmd(cosa, status);
+#endif
+ cosa_putdata8(cosa, status);
+ if (cosa->rxbitmap|cosa->txbitmap) {
+ cosa_putstatus(cosa, SR_RX_INT_ENA);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, SR_RX_INT_ENA);
+#endif
+ } else {
+ cosa_putstatus(cosa, 0);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, 0);
+#endif
+ }
+ }
+ if (!nolock)
+ spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+/*
+ * The "kickme" function: When the DMA times out, this is called to
+ * clean up the driver status.
+ * FIXME: Preliminary support, the interface is probably wrong.
+ */
+static void cosa_kick(struct cosa_data *cosa)
+{
+ unsigned flags, flags1;
+
+ printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name);
+
+ spin_lock_irqsave(&cosa->lock, flags);
+ cosa->rxtx = 0;
+
+ flags1 = claim_dma_lock();
+ disable_dma(cosa->dma);
+ clear_dma_ff(cosa->dma);
+ release_dma_lock(flags1);
+
+ /* FIXME: Anything else? */
+ put_driver_status_nolock(cosa);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+/*
+ * Check if the whole buffer is DMA-able. It means it is below the 16M of
+ * physical memory and doesn't span the 64k boundary. For now it seems
+ * SKB's never do this, but we'll check this anyway.
+ */
+static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
+{
+ static int count = 0;
+ unsigned long b = (unsigned long)buf;
+ if (b+len >= MAX_DMA_ADDRESS)
+ return 0;
+ if ((b^ (b+len)) & 0x10000) {
+ if (count++ < 5)
+ printk(KERN_INFO "%s: packet spanning a 64k boundary\n",
+ chan->name);
+ return 0;
+ }
+ return 1;
+}
+
+
+/* ---------- The SRP/COSA ROM monitor functions ---------- */
+
+/*
+ * Downloading SRP microcode: say "w" to SRP monitor, it answers by "w=",
+ * drivers need to say 4-digit hex number meaning start address of the microcode
+ * separated by a single space. Monitor replies by saying " =". Now driver
+ * has to write 4-digit hex number meaning the last byte address ended
+ * by a single space. Monitor has to reply with a space. Now the download
+ * begins. After the download monitor replies with "\r\n." (CR LF dot).
+ */
+static int download(struct cosa_data *cosa, char *microcode, int length, int address)
+{
+ int i;
+
+ if (put_wait_data(cosa, 'w') == -1) return -1;
+ if ((i=get_wait_data(cosa)) != 'w') { printk("dnld: 0x%04x\n",i); return -2;}
+ if (get_wait_data(cosa) != '=') return -3;
+
+ if (puthexnumber(cosa, address) < 0) return -4;
+ if (put_wait_data(cosa, ' ') == -1) return -10;
+ if (get_wait_data(cosa) != ' ') return -11;
+ if (get_wait_data(cosa) != '=') return -12;
+
+ if (puthexnumber(cosa, address+length-1) < 0) return -13;
+ if (put_wait_data(cosa, ' ') == -1) return -18;
+ if (get_wait_data(cosa) != ' ') return -19;
+
+ while (length--) {
+ char c;
+#ifndef SRP_DOWNLOAD_AT_BOOT
+ get_user_ret(c,microcode, -23);
+#else
+ c = *microcode;
+#endif
+ if (put_wait_data(cosa, c) == -1)
+ return -20;
+ microcode++;
+ }
+
+ if (get_wait_data(cosa) != '\r') return -21;
+ if (get_wait_data(cosa) != '\n') return -22;
+ if (get_wait_data(cosa) != '.') return -23;
+#if 0
+ printk(KERN_DEBUG "cosa%d: download completed.\n", cosa->num);
+#endif
+ return 0;
+}
+
+
+/*
+ * Starting microcode is done via the "g" command of the SRP monitor.
+ * The chat should be the following: "g" "g=" "<addr><CR>"
+ * "<CR><CR><LF><CR><LF>".
+ */
+static int startmicrocode(struct cosa_data *cosa, int address)
+{
+ if (put_wait_data(cosa, 'g') == -1) return -1;
+ if (get_wait_data(cosa) != 'g') return -2;
+ if (get_wait_data(cosa) != '=') return -3;
+
+ if (puthexnumber(cosa, address) < 0) return -4;
+ if (put_wait_data(cosa, '\r') == -1) return -5;
+
+ if (get_wait_data(cosa) != '\r') return -6;
+ if (get_wait_data(cosa) != '\r') return -7;
+ if (get_wait_data(cosa) != '\n') return -8;
+ if (get_wait_data(cosa) != '\r') return -9;
+ if (get_wait_data(cosa) != '\n') return -10;
+#if 0
+ printk(KERN_DEBUG "cosa%d: microcode started\n", cosa->num);
+#endif
+ return 0;
+}
+
+/*
+ * Reading memory is done via the "r" command of the SRP monitor.
+ * The chat is the following "r" "r=" "<addr> " " =" "<last_byte> " " "
+ * Then driver can read the data and the conversation is finished
+ * by SRP monitor sending "<CR><LF>." (dot at the end).
+ *
+ * This routine is not needed during the normal operation and serves
+ * for debugging purposes only.
+ */
+static int readmem(struct cosa_data *cosa, char *microcode, int length, int address)
+{
+ if (put_wait_data(cosa, 'r') == -1) return -1;
+ if ((get_wait_data(cosa)) != 'r') return -2;
+ if ((get_wait_data(cosa)) != '=') return -3;
+
+ if (puthexnumber(cosa, address) < 0) return -4;
+ if (put_wait_data(cosa, ' ') == -1) return -5;
+ if (get_wait_data(cosa) != ' ') return -6;
+ if (get_wait_data(cosa) != '=') return -7;
+
+ if (puthexnumber(cosa, address+length-1) < 0) return -8;
+ if (put_wait_data(cosa, ' ') == -1) return -9;
+ if (get_wait_data(cosa) != ' ') return -10;
+
+ while (length--) {
+ char c;
+ int i;
+ if ((i=get_wait_data(cosa)) == -1) {
+ printk (KERN_INFO "cosa: 0x%04x bytes remaining\n",
+ length);
+ return -11;
+ }
+ c=i;
+#if 1
+ put_user_ret(c,microcode, -23);
+#else
+ *microcode = c;
+#endif
+ microcode++;
+ }
+
+ if (get_wait_data(cosa) != '\r') return -21;
+ if (get_wait_data(cosa) != '\n') return -22;
+ if (get_wait_data(cosa) != '.') return -23;
+#if 0
+ printk(KERN_DEBUG "cosa%d: readmem completed.\n", cosa->num);
+#endif
+ return 0;
+}
+
+/*
+ * This function resets the device and reads the initial prompt
+ * of the device's ROM monitor.
+ */
+static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
+{
+ int i=0, id=0, prev=0, curr=0;
+
+ /* Reset the card ... */
+ cosa_putstatus(cosa, 0);
+ cosa_getdata8(cosa);
+ cosa_putstatus(cosa, SR_RST);
+#ifdef MODULE
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/2);
+ current->state = TASK_RUNNING;
+#else
+ udelay(5*100000);
+#endif
+ /* Disable all IRQs from the card */
+ cosa_putstatus(cosa, 0);
+
+ /*
+ * Try to read the ID string. The card then prints out the
+ * identification string ended by the "\n\x2e".
+ *
+ * The following loop is indexed through i (instead of id)
+ * to avoid looping forever when for any reason
+ * the port returns '\r', '\n' or '\x2e' permanently.
+ */
+ for (i=0; i<COSA_MAX_ID_STRING-1; i++, prev=curr) {
+ if ((curr = get_wait_data(cosa)) == -1) {
+ return -1;
+ }
+ curr &= 0xff;
+ if (curr != '\r' && curr != '\n' && curr != 0x2e)
+ idstring[id++] = curr;
+ if (curr == 0x2e && prev == '\n')
+ break;
+ }
+ /* Perhaps we should fail when i==COSA_MAX_ID_STRING-1 ? */
+ idstring[id] = '\0';
+ return id;
+}
+
+
+/* ---------- Auxiliary routines for COSA/SRP monitor ---------- */
+
+/*
+ * This routine gets the data byte from the card waiting for the SR_RX_RDY
+ * bit to be set in a loop. It should be used in the exceptional cases
+ * only (for example when resetting the card or downloading the firmware.
+ */
+static int get_wait_data(struct cosa_data *cosa)
+{
+ int retries = 1000;
+
+ while (--retries) {
+ /* read data and return them */
+ if (cosa_getstatus(cosa) & SR_RX_RDY) {
+ short r;
+ r = cosa_getdata8(cosa);
+#if 0
+ printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries);
+#endif
+ return r;
+ }
+ /* sleep if not ready to read */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ current->state = TASK_RUNNING;
+ }
+ printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+ cosa_getstatus(cosa));
+ return -1;
+}
+
+/*
+ * This routine puts the data byte to the card waiting for the SR_TX_RDY
+ * bit to be set in a loop. It should be used in the exceptional cases
+ * only (for example when resetting the card or downloading the firmware).
+ */
+static int put_wait_data(struct cosa_data *cosa, int data)
+{
+ int retries = 1000;
+ while (--retries) {
+ /* read data and return them */
+ if (cosa_getstatus(cosa) & SR_TX_RDY) {
+ cosa_putdata8(cosa, data);
+#if 0
+ printk(KERN_INFO "Putdata: %d retries\n", 999-retries);
+#endif
+ return 0;
+ }
+#if 0
+ /* sleep if not ready to read */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(1);
+ current->state = TASK_RUNNING;
+#endif
+ }
+ printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+ cosa->num, cosa_getstatus(cosa));
+ return -1;
+}
+
+/*
+ * The following routine puts the hexadecimal number into the SRP monitor
+ * and verifies the proper echo of the sent bytes. Returns 0 on success,
+ * negative number on failure (-1,-3,-5,-7) means that put_wait_data() failed,
+ * (-2,-4,-6,-8) means that reading echo failed.
+ */
+static int puthexnumber(struct cosa_data *cosa, int number)
+{
+ char temp[5];
+ int i;
+
+ /* Well, I should probably replace this by something faster. */
+ sprintf(temp, "%04X", number);
+ for (i=0; i<4; i++) {
+ if (put_wait_data(cosa, temp[i]) == -1) {
+ printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n",
+ cosa->num, i);
+ return -1-2*i;
+ }
+ if (get_wait_data(cosa) != temp[i]) {
+ printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n",
+ cosa->num, i);
+ return -2-2*i;
+ }
+ }
+ return 0;
+}
+
+
+/* ---------- Interrupt routines ---------- */
+
+/*
+ * There are three types of interrupt:
+ * At the beginning of transmit - this handled is in tx_interrupt(),
+ * at the beginning of receive - it is in rx_interrupt() and
+ * at the end of transmit/receive - it is the eot_interrupt() function.
+ * These functions are multiplexed by cosa_interrupt() according to the
+ * COSA status byte. I have moved the rx/tx/eot interrupt handling into
+ * separate functions to make it more readable. These functions are inline,
+ * so there should be no overhead of function call.
+ */
+
+/*
+ * Transmit interrupt routine - called when COSA is willing to obtain
+ * data from the OS. The most tricky part of the routine is selection
+ * of channel we (OS) want to send packet for. For SRP we should probably
+ * use the round-robin approach. The newer COSA firmwares have a simple
+ * flow-control - in the status word has bits 2 and 3 set to 1 means that the
+ * channel 0 or 1 doesn't want to receive data.
+ */
+static inline void tx_interrupt(struct cosa_data *cosa, int status)
+{
+ unsigned long flags, flags1;
+#ifdef DEBUG_IRQS
+ printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n",
+ cosa->num, status);
+#endif
+ spin_lock_irqsave(&cosa->lock, flags);
+ set_bit(TXBIT, &cosa->rxtx);
+ if (!test_bit(IRQBIT, &cosa->rxtx)) {
+ /* flow control */
+ int i=0;
+ do {
+ if (i++ > cosa->nchannels) {
+ printk(KERN_WARNING
+ "%s: No channel wants data in TX IRQ\n",
+ cosa->name);
+ clear_bit(TXBIT, &cosa->rxtx);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return;
+ }
+ cosa->txchan++;
+ if (cosa->txchan >= cosa->nchannels)
+ cosa->txchan = 0;
+ } while ((!(cosa->txbitmap & (1<<cosa->txchan)))
+ || status & (1<<(cosa->txchan+DRIVER_TXMAP_SHIFT)));
+
+ cosa->txsize = cosa->chan[cosa->txchan].txsize;
+ if (cosa_dma_able(cosa->chan+cosa->txchan,
+ cosa->chan[cosa->txchan].txbuf, cosa->txsize)) {
+ cosa->txbuf = cosa->chan[cosa->txchan].txbuf;
+ } else {
+ memcpy(cosa->bouncebuf, cosa->chan[cosa->txchan].txbuf,
+ cosa->txsize);
+ cosa->txbuf = cosa->bouncebuf;
+ }
+ }
+
+ if (is_8bit(cosa)) {
+ if (!test_bit(IRQBIT, &cosa->rxtx)) {
+ cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
+ ((cosa->txsize >> 8) & 0x1f));
+ cosa_putstatus(cosa, SR_TX_INT_ENA);
+#ifdef DEBUG_IO
+ debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)|
+ ((cosa->txsize >> 8) & 0x1f));
+ debug_status_out(cosa, SR_TX_INT_ENA);
+ debug_data_in(cosa, cosa_getdata8(cosa));
+#else
+ cosa_getdata8(cosa);
+#endif
+ set_bit(IRQBIT, &cosa->rxtx);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return;
+ } else {
+ clear_bit(IRQBIT, &cosa->rxtx);
+ cosa_putstatus(cosa, 0);
+ cosa_putdata8(cosa, cosa->txsize&0xff);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, 0);
+ debug_data_out(cosa, cosa->txsize&0xff);
+#endif
+ }
+ } else {
+ cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
+ | (cosa->txsize & 0x1fff));
+ cosa_getdata16(cosa);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000)
+ | (cosa->txsize & 0x1fff));
+ debug_data_in(cosa, cosa_getdata16(cosa));
+#else
+ cosa_getdata16(cosa);
+#endif
+ }
+
+ /* start the DMA */
+ flags1 = claim_dma_lock();
+ disable_dma(cosa->dma);
+ clear_dma_ff(cosa->dma);
+ set_dma_mode(cosa->dma, DMA_MODE_WRITE);
+ set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
+ set_dma_count(cosa->dma, cosa->txsize);
+ enable_dma(cosa->dma);
+ release_dma_lock(flags1);
+ cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
+#endif
+ spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static inline void rx_interrupt(struct cosa_data *cosa, int status)
+{
+ unsigned long flags;
+#ifdef DEBUG_IRQS
+ printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num);
+#endif
+
+ spin_lock_irqsave(&cosa->lock, flags);
+ set_bit(RXBIT, &cosa->rxtx);
+
+ if (is_8bit(cosa)) {
+ if (!test_bit(IRQBIT, &cosa->rxtx)) {
+ set_bit(IRQBIT, &cosa->rxtx);
+ cosa_putstatus(cosa, 0);
+ cosa->rxsize = cosa_getdata8(cosa) <<8;
+#ifdef DEBUG_IO
+ debug_status_out(cosa, 0);
+ debug_data_in(cosa, cosa->rxsize >> 8);
+#endif
+ put_driver_status_nolock(cosa);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ return;
+ } else {
+ clear_bit(IRQBIT, &cosa->rxtx);
+ cosa_putstatus(cosa, 0);
+ cosa->rxsize |= cosa_getdata8(cosa) & 0xff;
+#ifdef DEBUG_IO
+ debug_status_out(cosa, 0);
+ debug_data_in(cosa, cosa->rxsize & 0xff);
+#endif
+#if 0
+ printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ cosa->num, cosa->rxsize);
+#endif
+ }
+ } else {
+ cosa->rxsize = cosa_getdata16(cosa);
+ cosa_putstatus(cosa, 0);
+ cosa_putdata8(cosa, DRIVER_RX_READY);
+#ifdef DEBUG_IO
+ debug_data_in(cosa, cosa->rxsize);
+ debug_status_out(cosa, 0);
+ debug_cmd_out(cosa, DRIVER_RX_READY);
+#endif
+#if 0
+ printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+ cosa->num, cosa->rxsize);
+#endif
+ }
+ if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
+ printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n",
+ cosa->name, cosa->rxsize);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+ goto reject;
+ }
+ cosa->rxchan = cosa->chan + ((cosa->rxsize & 0xe000) >> 13);
+ cosa->rxsize &= 0x1fff;
+ spin_unlock_irqrestore(&cosa->lock, flags);
+
+ cosa->rxbuf = NULL;
+ if (cosa->rxchan->setup_rx)
+ cosa->rxbuf = cosa->rxchan->setup_rx(cosa->rxchan, cosa->rxsize);
+
+ if (!cosa->rxbuf) {
+reject: /* Reject the packet */
+ printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
+ cosa->num, cosa->rxchan->num);
+ /* FIXME: This works for COSA only (not SRP) */
+ cosa->rxtx = 0;
+ put_driver_status(cosa);
+ return;
+ }
+
+ /* start the DMA */
+ flags = claim_dma_lock();
+ disable_dma(cosa->dma);
+ clear_dma_ff(cosa->dma);
+ set_dma_mode(cosa->dma, DMA_MODE_READ);
+ if (cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize & 0x1fff)) {
+ set_dma_addr(cosa->dma, virt_to_bus(cosa->rxbuf));
+ } else {
+ set_dma_addr(cosa->dma, virt_to_bus(cosa->bouncebuf));
+ }
+ set_dma_count(cosa->dma, (cosa->rxsize&0x1fff));
+ enable_dma(cosa->dma);
+ release_dma_lock(flags);
+ spin_lock_irqsave(&cosa->lock, flags);
+ cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+#ifdef DEBUG_IO
+ debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+#endif
+ spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void inline eot_interrupt(struct cosa_data *cosa, int status)
+{
+ unsigned long flags, flags1;
+ spin_lock_irqsave(&cosa->lock, flags);
+ if (test_bit(TXBIT, &cosa->rxtx)) {
+ struct channel_data *chan = cosa->chan+cosa->txchan;
+#ifdef DEBUG_IRQS
+ printk(KERN_INFO "cosa%d: end of transfer.\n", cosa->num);
+#endif
+ if (chan->tx_done)
+ if (chan->tx_done(chan, cosa->txsize))
+ clear_bit(chan->num, &cosa->txbitmap);
+ } else if (test_bit(RXBIT, &cosa->rxtx)) {
+#ifdef DEBUG_DATA
+ {
+ int i;
+ printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num,
+ cosa->rxchan->num, cosa->rxsize);
+ for (i=0; i<cosa->rxsize; i++)
+ printk (" %02x", cosa->rxbuf[i]&0xff);
+ printk("\n");
+ }
+#endif
+ if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
+ memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
+ if (cosa->rxchan->rx_done)
+ if (cosa->rxchan->rx_done(cosa->rxchan))
+ clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
+ } else {
+ printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n",
+ cosa->num);
+ }
+ /*
+ * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
+ * cleared anyway).
+ */
+ flags1 = claim_dma_lock();
+ disable_dma(cosa->dma);
+ clear_dma_ff(cosa->dma);
+ release_dma_lock(flags1);
+ cosa->rxtx = 0;
+ put_driver_status_nolock(cosa);
+ spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
+{
+ int status;
+ int count = 0;
+ struct cosa_data *cosa = cosa_;
+again:
+ status = cosa_getstatus(cosa);
+#ifdef DEBUG_IRQS
+ printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num,
+ status & 0xff);
+#endif
+#ifdef DEBUG_IO
+ debug_status_in(cosa, status);
+#endif
+ switch (status & SR_CMD_FROM_SRP_MASK) {
+ case SR_DOWN_REQUEST:
+ tx_interrupt(cosa, status);
+ break;
+ case SR_UP_REQUEST:
+ rx_interrupt(cosa, status);
+ break;
+ case SR_END_OF_TRANSFER:
+ eot_interrupt(cosa, status);
+ break;
+ default:
+ /* We may be too fast for SRP. Try to wait a bit more. */
+ if (count++ < 100) {
+ udelay(100);
+ goto again;
+ }
+ printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
+ cosa->num, status & 0xff, count);
+ }
+#ifdef DEBUG_IRQS
+ if (count)
+ printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n",
+ cosa->name, count);
+ else
+ printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
+#endif
+}
+
+
+/* ---------- I/O debugging routines ---------- */
+/*
+ * These routines can be used to monitor COSA/SRP I/O and to printk()
+ * the data being transfered on the data and status I/O port in a
+ * readable way.
+ */
+
+#ifdef DEBUG_IO
+static void debug_status_in(struct cosa_data *cosa, int status)
+{
+ char *s;
+ switch(status & SR_CMD_FROM_SRP_MASK) {
+ case SR_UP_REQUEST:
+ s = "RX_REQ";
+ break;
+ case SR_DOWN_REQUEST:
+ s = "TX_REQ";
+ break;
+ case SR_END_OF_TRANSFER:
+ s = "ET_REQ";
+ break;
+ default:
+ s = "NO_REQ";
+ break;
+ }
+ printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n",
+ cosa->name,
+ status,
+ status & SR_USR_RQ ? "USR_RQ|":"",
+ status & SR_TX_RDY ? "TX_RDY|":"",
+ status & SR_RX_RDY ? "RX_RDY|":"",
+ s);
+}
+
+static void debug_status_out(struct cosa_data *cosa, int status)
+{
+ printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
+ cosa->name,
+ status,
+ status & SR_RX_DMA_ENA ? "RXDMA|":"!rxdma|",
+ status & SR_TX_DMA_ENA ? "TXDMA|":"!txdma|",
+ status & SR_RST ? "RESET|":"",
+ status & SR_USR_INT_ENA ? "USRINT|":"!usrint|",
+ status & SR_TX_INT_ENA ? "TXINT|":"!txint|",
+ status & SR_RX_INT_ENA ? "RXINT":"!rxint");
+}
+
+static void debug_data_in(struct cosa_data *cosa, int data)
+{
+ printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data);
+}
+
+static void debug_data_out(struct cosa_data *cosa, int data)
+{
+ printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data);
+}
+
+static void debug_data_cmd(struct cosa_data *cosa, int data)
+{
+ printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n",
+ cosa->name, data,
+ data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
+ data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
+}
+#endif
+
+/* EOF -- this file has not been truncated */
diff --git a/drivers/net/cosa.h b/drivers/net/cosa.h
new file mode 100644
index 000000000..09f2e243d
--- /dev/null
+++ b/drivers/net/cosa.h
@@ -0,0 +1,102 @@
+/* $Id: cosa.h,v 1.5 1998/12/24 12:40:18 kas Exp $ */
+
+/*
+ * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak <kas@fi.muni.cz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef COSA_H__
+#define COSA_H__
+
+#include <linux/ioctl.h>
+
+#ifdef __KERNEL__
+/* status register - output bits */
+#define SR_RX_DMA_ENA 0x04 /* receiver DMA enable bit */
+#define SR_TX_DMA_ENA 0x08 /* transmitter DMA enable bit */
+#define SR_RST 0x10 /* SRP reset */
+#define SR_USR_INT_ENA 0x20 /* user interrupt enable bit */
+#define SR_TX_INT_ENA 0x40 /* transmitter interrupt enable bit */
+#define SR_RX_INT_ENA 0x80 /* receiver interrupt enable bit */
+
+/* status register - input bits */
+#define SR_USR_RQ 0x20 /* user interupt request pending */
+#define SR_TX_RDY 0x40 /* transmitter empty (ready) */
+#define SR_RX_RDY 0x80 /* receiver data ready */
+
+#define SR_UP_REQUEST 0x02 /* request from SRP to transfer data
+ up to PC */
+#define SR_DOWN_REQUEST 0x01 /* SRP is able to transfer data down
+ from PC to SRP */
+#define SR_END_OF_TRANSFER 0x03 /* SRP signalize end of
+ transfer (up or down) */
+
+#define SR_CMD_FROM_SRP_MASK 0x03 /* mask to get SRP command */
+
+/* bits in driver status byte definitions : */
+#define SR_RDY_RCV 0x01 /* ready to receive packet */
+#define SR_RDY_SND 0x02 /* ready to send packet */
+#define SR_CMD_PND 0x04 /* command pending */ /* not currently used */
+
+/* ???? */
+#define SR_PKT_UP 0x01 /* transfer of packet up in progress */
+#define SR_PKT_DOWN 0x02 /* transfer of packet down in progress */
+
+#endif /* __KERNEL__ */
+
+#define SR_LOAD_ADDR 0x4400 /* SRP microcode load address */
+#define SR_START_ADDR 0x4400 /* SRP microcode start address */
+
+#define COSA_LOAD_ADDR 0x400 /* SRP microcode load address */
+#define COSA_MAX_FIRMWARE_SIZE 0x10000
+
+/* ioctls */
+struct cosa_download {
+ int addr, len;
+ char *code;
+};
+
+/* Reset the device */
+#define COSAIORSET _IO('C',0xf0)
+
+/* Start microcode at given address */
+#define COSAIOSTRT _IOW('C',0xf1,sizeof(int))
+
+/* Read the block from the device memory */
+#define COSAIORMEM _IOR('C',0xf2,sizeof(struct cosa_download *))
+
+/* Write the block to the device memory (i.e. download the microcode) */
+#define COSAIODOWNLD _IOW('C',0xf2,sizeof(struct cosa_download *))
+
+/* Read the device type (one of "srp", "cosa", and "cosa8" for now) */
+#define COSAIORTYPE _IOR('C',0xf3,sizeof(char *))
+
+/* Read the device identification string */
+#define COSAIORIDSTR _IOR('C',0xf4,sizeof(char *))
+/* Maximum length of the identification string. */
+#define COSA_MAX_ID_STRING 128
+
+/* Increment/decrement the module usage count :-) */
+/* #define COSAIOMINC _IO('C',0xf5) */
+/* #define COSAIOMDEC _IO('C',0xf6) */
+
+/* Get the total number of cards installed */
+#define COSAIONRCARDS _IO('C',0xf7)
+
+/* Get the number of channels on this card */
+#define COSAIONRCHANS _IO('C',0xf8)
+
+#endif /* !COSA_H__ */
diff --git a/drivers/net/daynaport.c b/drivers/net/daynaport.c
index 00c0ed9b6..777a1dcab 100644
--- a/drivers/net/daynaport.c
+++ b/drivers/net/daynaport.c
@@ -340,13 +340,13 @@ int ns8390_probe1(struct device *dev, int word16, char *model_name, int type, in
{
static unsigned version_printed = 0;
- static int fwrd4_offsets[16]={
+ static u32 fwrd4_offsets[16]={
0, 4, 8, 12,
16, 20, 24, 28,
32, 36, 40, 44,
48, 52, 56, 60
};
- static int back4_offsets[16]={
+ static u32 back4_offsets[16]={
60, 56, 52, 48,
44, 40, 36, 32,
28, 24, 20, 16,
diff --git a/drivers/net/de4x5.c b/drivers/net/de4x5.c
index bbc86f2a2..0ce0e89f9 100644
--- a/drivers/net/de4x5.c
+++ b/drivers/net/de4x5.c
@@ -415,11 +415,12 @@
alignment for Alpha's and avoid their unaligned
access traps. This flag is merely for log messages:
should do something more definitive though...
+ 0.543 30-Dec-98 Add SMP spin locking.
=========================================================================
*/
-static const char *version = "de4x5.c:V0.542 1998/9/15 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.543 1998/12/30 davies@maniac.ultranet.com\n";
#include <linux/config.h>
#include <linux/module.h>
@@ -443,6 +444,7 @@ static const char *version = "de4x5.c:V0.542 1998/9/15 davies@maniac.ultranet.co
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <asm/uaccess.h>
+#include <asm/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -508,11 +510,11 @@ struct sia_phy {
** recognised by this driver.
*/
static struct phy_table phy_info[] = {
- {0, NATIONAL_TX, 1, {0x19, 0x40, 0x00}}, /* National TX */
- {1, BROADCOM_T4, 1, {0x10, 0x02, 0x02}}, /* Broadcom T4 */
- {0, SEEQ_T4 , 1, {0x12, 0x10, 0x10}}, /* SEEQ T4 */
- {0, CYPRESS_T4 , 1, {0x05, 0x20, 0x20}}, /* Cypress T4 */
- {0, 0x7810 , 1, {0x05, 0x0380, 0x0380}} /* Level One? */
+ {0, NATIONAL_TX, 1, {0x19, 0x40, 0x00}}, /* National TX */
+ {1, BROADCOM_T4, 1, {0x10, 0x02, 0x02}}, /* Broadcom T4 */
+ {0, SEEQ_T4 , 1, {0x12, 0x10, 0x10}}, /* SEEQ T4 */
+ {0, CYPRESS_T4 , 1, {0x05, 0x20, 0x20}}, /* Cypress T4 */
+ {0, 0x7810 , 1, {0x14, 0x0800, 0x0800}} /* Level One LTX970 */
};
/*
@@ -759,7 +761,8 @@ struct de4x5_private {
int tx_new, tx_old; /* TX descriptor ring pointers */
char setup_frame[SETUP_FRAME_LEN]; /* Holds MCA and PA info. */
char frame[64]; /* Min sized packet for loopback*/
- struct net_device_stats stats; /* Public stats */
+ spinlock_t lock; /* Adapter specific spinlock */
+ struct net_device_stats stats; /* Public stats */
struct {
u_int bins[DE4X5_PKT_STAT_SZ]; /* Private stats counters */
u_int unicast;
@@ -1192,6 +1195,7 @@ de4x5_hw_init(struct device *dev, u_long iobase))
lp->timeout = -1;
lp->useSROM = useSROM;
memcpy((char *)&lp->srom,(char *)&bus.srom,sizeof(struct de4x5_srom));
+ lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
de4x5_parse_params(dev);
/*
@@ -1345,7 +1349,7 @@ de4x5_open(struct device *dev)
** Re-initialize the DE4X5...
*/
status = de4x5_init(dev);
-
+ lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
lp->state = OPEN;
de4x5_dbg_open(dev);
@@ -1497,6 +1501,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
u_long iobase = dev->base_addr;
int status = 0;
+ u_long flags = 0;
test_and_set_bit(0, (void*)&dev->tbusy); /* Stop send re-tries */
if (lp->tx_enable == NO) { /* Cannot send for now */
@@ -1508,9 +1513,9 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
** interrupts are lost by delayed descriptor status updates relative to
** the irq assertion, especially with a busy PCI bus.
*/
- cli();
+ spin_lock_irqsave(&lp->lock, flags);
de4x5_tx(dev);
- sti();
+ spin_unlock_irqrestore(&lp->lock, flags);
/* Test if cache is already locked - requeue skb if so */
if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt)
@@ -1534,7 +1539,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
}
while (skb && !dev->tbusy && !lp->tx_skb[lp->tx_new]) {
- cli();
+ spin_lock_irqsave(&lp->lock, flags);
test_and_set_bit(0, (void*)&dev->tbusy);
load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb);
lp->stats.tx_bytes += skb->len;
@@ -1547,7 +1552,7 @@ de4x5_queue_pkt(struct sk_buff *skb, struct device *dev)
dev->tbusy = 0; /* Another pkt may be queued */
}
skb = de4x5_get_cache(dev);
- sti();
+ spin_unlock_irqrestore(&lp->lock, flags);
}
if (skb) de4x5_putb_cache(dev, skb);
}
@@ -1581,6 +1586,7 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
lp = (struct de4x5_private *)dev->priv;
+ spin_lock(&lp->lock);
iobase = dev->base_addr;
DISABLE_IRQs; /* Ensure non re-entrancy */
@@ -1628,6 +1634,7 @@ de4x5_interrupt(int irq, void *dev_id, struct pt_regs *regs)
lp->interrupt = UNMASK_INTERRUPTS;
ENABLE_IRQs;
+ spin_unlock(&lp->lock);
return;
}
@@ -2069,7 +2076,9 @@ eisa_probe(struct device *dev, u_long ioaddr))
irq = inb(EISA_REG0);
irq = de4x5_irq[(irq >> 1) & 0x03];
- if (is_DC2114x) device |= (cfrv & CFRV_RN);
+ if (is_DC2114x) {
+ device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+ }
lp->chipset = device;
/* Write the PCI Configuration Registers */
@@ -2165,7 +2174,9 @@ pci_probe(struct device *dev, u_long ioaddr))
lp->bus_num = pb;
/* Set the chipset information */
- if (is_DC2114x) device |= (cfrv & CFRV_RN);
+ if (is_DC2114x) {
+ device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+ }
lp->chipset = device;
/* Get the board I/O address (64 bits on sparc64) */
@@ -2249,7 +2260,9 @@ srom_search(struct pci_dev *dev))
lp->bus_num = pb;
/* Set the chipset information */
- if (is_DC2114x) device |= (cfrv & CFRV_RN);
+ if (is_DC2114x) {
+ device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
+ }
lp->chipset = device;
/* Get the board I/O address (64 bits on sparc64) */
@@ -3223,18 +3236,19 @@ de4x5_init_connection(struct device *dev)
{
struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
u_long iobase = dev->base_addr;
+ u_long flags = 0;
if (lp->media != lp->c_media) {
de4x5_dbg_media(dev);
lp->c_media = lp->media; /* Stop scrolling media messages */
}
- cli();
+ spin_lock_irqsave(&lp->lock, flags);
de4x5_rst_desc_ring(dev);
de4x5_setup_intr(dev);
lp->tx_enable = YES;
dev->tbusy = 0;
- sti();
+ spin_unlock_irqrestore(&lp->lock, flags);
outl(POLL_DEMAND, DE4X5_TPD);
mark_bh(NET_BH);
@@ -5524,116 +5538,90 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
u16 sval[72];
u32 lval[36];
} tmp;
+ u_long flags = 0;
switch(ioc->cmd) {
case DE4X5_GET_HWADDR: /* Get the hardware address */
ioc->len = ETH_ALEN;
- status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
- if (status)
- break;
+ if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
for (i=0; i<ETH_ALEN; i++) {
tmp.addr[i] = dev->dev_addr[i];
}
copy_to_user(ioc->data, tmp.addr, ioc->len);
-
break;
+
case DE4X5_SET_HWADDR: /* Set the hardware address */
- status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN);
- if (status)
- break;
- status = -EPERM;
- if (!capable(CAP_NET_ADMIN))
- break;
- status = 0;
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN)) return -EFAULT;
copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
for (i=0; i<ETH_ALEN; i++) {
dev->dev_addr[i] = tmp.addr[i];
}
build_setup_frame(dev, PHYS_ADDR_ONLY);
/* Set up the descriptor and give ownership to the card */
- while (test_and_set_bit(0, (void *)&dev->tbusy) != 0);
+ while (test_and_set_bit(0, (void *)&dev->tbusy) != 0) barrier();
load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
SETUP_FRAME_LEN, NULL);
lp->tx_new = (++lp->tx_new) % lp->txRingSize;
outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
dev->tbusy = 0; /* Unlock the TX ring */
-
break;
+
case DE4X5_SET_PROM: /* Set Promiscuous Mode */
- if (capable(CAP_NET_ADMIN)) {
- omr = inl(DE4X5_OMR);
- omr |= OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags |= IFF_PROMISC;
- } else {
- status = -EPERM;
- }
-
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ omr = inl(DE4X5_OMR);
+ omr |= OMR_PR;
+ outl(omr, DE4X5_OMR);
+ dev->flags |= IFF_PROMISC;
break;
+
case DE4X5_CLR_PROM: /* Clear Promiscuous Mode */
- if (capable(CAP_NET_ADMIN)) {
- omr = inl(DE4X5_OMR);
- omr &= ~OMR_PR;
- outb(omr, DE4X5_OMR);
- dev->flags &= ~IFF_PROMISC;
- } else {
- status = -EPERM;
- }
-
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ omr = inl(DE4X5_OMR);
+ omr &= ~OMR_PR;
+ outb(omr, DE4X5_OMR);
+ dev->flags &= ~IFF_PROMISC;
break;
+
case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */
printk("%s: Boo!\n", dev->name);
-
break;
+
case DE4X5_MCA_EN: /* Enable pass all multicast addressing */
- if (capable(CAP_NET_ADMIN)) {
- omr = inl(DE4X5_OMR);
- omr |= OMR_PM;
- outl(omr, DE4X5_OMR);
- } else {
- status = -EPERM;
- }
-
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ omr = inl(DE4X5_OMR);
+ omr |= OMR_PM;
+ outl(omr, DE4X5_OMR);
break;
+
case DE4X5_GET_STATS: /* Get the driver statistics */
ioc->len = sizeof(lp->pktStats);
- status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len);
- if (status)
- break;
-
- cli();
+ if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
+ spin_lock_irqsave(&lp->lock, flags);
copy_to_user(ioc->data, &lp->pktStats, ioc->len);
- sti();
-
+ spin_unlock_irqrestore(&lp->lock, flags);
break;
+
case DE4X5_CLR_STATS: /* Zero out the driver statistics */
- if (capable(CAP_NET_ADMIN)) {
- cli();
- memset(&lp->pktStats, 0, sizeof(lp->pktStats));
- sti();
- } else {
- status = -EPERM;
- }
-
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ spin_lock_irqsave(&lp->lock, flags);
+ memset(&lp->pktStats, 0, sizeof(lp->pktStats));
+ spin_unlock_irqrestore(&lp->lock, flags);
break;
+
case DE4X5_GET_OMR: /* Get the OMR Register contents */
tmp.addr[0] = inl(DE4X5_OMR);
- if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, 1))) {
- copy_to_user(ioc->data, tmp.addr, 1);
- }
-
+ if (verify_area(VERIFY_WRITE, ioc->data, 1)) return -EFAULT;
+ copy_to_user(ioc->data, tmp.addr, 1);
break;
+
case DE4X5_SET_OMR: /* Set the OMR Register contents */
- if (capable(CAP_NET_ADMIN)) {
- if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, 1))) {
- copy_from_user(tmp.addr, ioc->data, 1);
- outl(tmp.addr[0], DE4X5_OMR);
- }
- } else {
- status = -EPERM;
- }
-
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (verify_area(VERIFY_READ, ioc->data, 1)) return -EFAULT;
+ copy_from_user(tmp.addr, ioc->data, 1);
+ outl(tmp.addr[0], DE4X5_OMR);
break;
+
case DE4X5_GET_REG: /* Get the DE4X5 Registers */
j = 0;
tmp.lval[0] = inl(DE4X5_STS); j+=4;
@@ -5645,9 +5633,8 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
tmp.lval[6] = inl(DE4X5_STRR); j+=4;
tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
ioc->len = j;
- if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
- copy_to_user(ioc->data, tmp.addr, ioc->len);
- }
+ if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
+ copy_to_user(ioc->data, tmp.addr, ioc->len);
break;
#define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */
@@ -5736,14 +5723,13 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
tmp.addr[j++] = dev->tbusy;
ioc->len = j;
- if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
- copy_to_user(ioc->data, tmp.addr, ioc->len);
- }
-
+ if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
+ copy_to_user(ioc->data, tmp.addr, ioc->len);
break;
+
*/
default:
- status = -EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
return status;
@@ -5775,6 +5761,12 @@ init_module(void)
if (!mdev) mdev = p;
if (register_netdev(p) != 0) {
+ struct de4x5_private *lp = (struct de4x5_private *)p->priv;
+ if (lp) {
+ release_region(p->base_addr, (lp->bus == PCI ?
+ DE4X5_PCI_TOTAL_SIZE :
+ DE4X5_EISA_TOTAL_SIZE));
+ }
kfree(p);
} else {
status = 0; /* At least one adapter will work */
diff --git a/drivers/net/de4x5.h b/drivers/net/de4x5.h
index 24ab33873..6e5aeae0f 100644
--- a/drivers/net/de4x5.h
+++ b/drivers/net/de4x5.h
@@ -121,6 +121,7 @@
#define DC2114x DC2114x_DID
#define DC21142 (DC2114x_DID | 0x0010)
#define DC21143 (DC2114x_DID | 0x0030)
+#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */
#define is_DC21040 ((vendor == DC21040_VID) && (device == DC21040_DID))
#define is_DC21041 ((vendor == DC21041_VID) && (device == DC21041_DID))
diff --git a/drivers/net/dgrs.c b/drivers/net/dgrs.c
index c379b3a43..2d4e08482 100644
--- a/drivers/net/dgrs.c
+++ b/drivers/net/dgrs.c
@@ -1098,7 +1098,7 @@ dgrs_download(struct device *dev0))
*/
proc_reset(dev0, 0);
- for (i = jiffies + 8 * HZ; i > jiffies; )
+ for (i = jiffies + 8 * HZ; time_after(i, jiffies); )
{
if (priv0->bcomm->bc_status >= BC_RUN)
break;
@@ -1196,7 +1196,7 @@ dgrs_probe1(struct device *dev))
return (rc);
priv->intrcnt = 0;
- for (i = jiffies + 2*HZ + HZ/2; i > jiffies; )
+ for (i = jiffies + 2*HZ + HZ/2; time_after(i, jiffies); )
if (priv->intrcnt >= 2)
break;
if (priv->intrcnt < 2)
diff --git a/drivers/net/dgrs_i82596.h b/drivers/net/dgrs_i82596.h
index 614efe746..b1c83b5b9 100644
--- a/drivers/net/dgrs_i82596.h
+++ b/drivers/net/dgrs_i82596.h
@@ -393,7 +393,7 @@ typedef volatile struct
/* cmd halfword values */
#define I596_SCB_ACK 0xF000 /* ACKNOWLEDGMENTS */
#define I596_SCB_ACK_CX 0x8000 /* Ack command completion */
-#define I596_SCB_ACK_FR 0x4000 /* Ack recieved frame */
+#define I596_SCB_ACK_FR 0x4000 /* Ack received frame */
#define I596_SCB_ACK_CNA 0x2000 /* Ack command unit not active */
#define I596_SCB_ACK_RNR 0x1000 /* Ack rcv unit not ready */
#define I596_SCB_ACK_ALL 0xF000 /* Ack everything */
@@ -419,7 +419,7 @@ typedef volatile struct
/* status halfword values */
#define I596_SCB_STAT 0xF000 /* STATUS */
#define I596_SCB_CX 0x8000 /* command completion */
-#define I596_SCB_FR 0x4000 /* recieved frame */
+#define I596_SCB_FR 0x4000 /* received frame */
#define I596_SCB_CNA 0x2000 /* command unit not active */
#define I596_SCB_RNR 0x1000 /* rcv unit not ready */
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index d95d34a4a..529158e81 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -449,7 +449,6 @@ cleanup_module(void)
void *priv = dev->priv;
/* NB: e21_close() handles free_irq */
release_region(dev->base_addr, E21_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index b26a1bfc0..08a9a17ac 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -8,7 +8,7 @@
according to the terms of the GNU Public License,
incorporated herein by reference.
- The author may be reached at bao.ha@srs.gov
+ The author may be reached at bao.ha@srs.gov
or 418 Hastings Place, Martinez, GA 30907.
Things remaining to do:
@@ -23,6 +23,38 @@
This is a compatibility hardware problem.
Versions:
+ 0.11d added __initdata, __initfunc stuff; call spin_lock_init
+ in eepro_probe1. Replaced "eepro" by dev->name. Augmented
+ the code protected by spin_lock in interrupt routine
+ (PdP, 12/12/1998)
+ 0.11c minor cleanup (PdP, RMC, 09/12/1998)
+ 0.11b Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module
+ under 2.1.xx. Debug messages are flagged as KERN_DEBUG to
+ avoid console flooding. Added locking at critical parts. Now
+ the dawn thing is SMP safe.
+ 0.11a Attempt to get 2.1.xx support up (RMC)
+ 0.11 Brian Candler added support for multiple cards. Tested as
+ a module, no idea if it works when compiled into kernel.
+
+ 0.10e Rick Bressler notified me that ifconfig up;ifconfig down fails
+ because the irq is lost somewhere. Fixed that by moving
+ request_irq and free_irq to eepro_open and eepro_close respectively.
+ 0.10d Ugh! Now Wakeup works. Was seriously broken in my first attempt.
+ I'll need to find a way to specify an ioport other than
+ the default one in the PnP case. PnP definitively sucks.
+ And, yes, this is not the only reason.
+ 0.10c PnP Wakeup Test for 595FX. uncomment #define PnPWakeup;
+ to use.
+ 0.10b Should work now with (some) Pro/10+. At least for
+ me (and my two cards) it does. _No_ guarantee for
+ function with non-Pro/10+ cards! (don't have any)
+ (RMC, 9/11/96)
+
+ 0.10 Added support for the Etherexpress Pro/10+. The
+ IRQ map was changed significantly from the old
+ pro/10. The new interrupt map was provided by
+ Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu).
+ (BCH, 9/3/96)
0.09 Fixed a race condition in the transmit algorithm,
which causes crashes under heavy load with fast
@@ -38,7 +70,7 @@
0.07a Fix a stat report which counts every packet as a
heart-beat failure. (BCH, 6/3/95)
- 0.07 Modified to support all other 82595-based lan cards.
+ 0.07 Modified to support all other 82595-based lan cards.
The IRQ vector of the EtherExpress Pro will be set
according to the value saved in the EEPROM. For other
cards, I will do autoirq_request() to grab the next
@@ -48,37 +80,37 @@
print out format. (BCH, 3/9/95 and 3/14/95)
0.06 First stable release that I am comfortable with. (BCH,
- 3/2/95)
+ 3/2/95)
- 0.05 Complete testing of multicast. (BCH, 2/23/95)
+ 0.05 Complete testing of multicast. (BCH, 2/23/95)
- 0.04 Adding multicast support. (BCH, 2/14/95)
+ 0.04 Adding multicast support. (BCH, 2/14/95)
- 0.03 First widely alpha release for public testing.
- (BCH, 2/14/95)
+ 0.03 First widely alpha release for public testing.
+ (BCH, 2/14/95)
*/
static const char *version =
- "eepro.c: v0.09 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n";
+ "eepro.c: v0.11d 08/12/1998 dupuis@lei.ucl.ac.be\n";
#include <linux/module.h>
/*
Sources:
- This driver wouldn't have been written without the availability
- of the Crynwr's Lan595 driver source code. It helps me to
- familiarize with the 82595 chipset while waiting for the Intel
- documentation. I also learned how to detect the 82595 using
+ This driver wouldn't have been written without the availability
+ of the Crynwr's Lan595 driver source code. It helps me to
+ familiarize with the 82595 chipset while waiting for the Intel
+ documentation. I also learned how to detect the 82595 using
the packet driver's technique.
This driver is written by cutting and pasting the skeleton.c driver
provided by Donald Becker. I also borrowed the EEPROM routine from
Donald Becker's 82586 driver.
- Datasheet for the Intel 82595 (including the TX and FX version). It
- provides just enough info that the casual reader might think that it
+ Datasheet for the Intel 82595 (including the TX and FX version). It
+ provides just enough info that the casual reader might think that it
documents the i82595.
The User Manual for the 82595. It provides a lot of the missing
@@ -101,22 +133,60 @@ static const char *version =
#include <asm/io.h>
#include <asm/dma.h>
#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+/* need to remove these asap */
+/* 2.1.xx compatibility macros... */
+/* */
+
+
+#include <linux/version.h>
+
+/* For linux 2.1.xx */
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+
+#include <asm/spinlock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
+/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
+#define SLOW_DOWN inb(0x80)
+/* udelay(2) */
+#define compat_init_func(X) __initfunc(X)
+#define compat_init_data __initdata
+
+#else
+/* for 2.x */
+
+#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
+#define test_and_set_bit(a,b) set_bit((a),(b))
+#define SLOW_DOWN SLOW_DOWN_IO
+#define compat_init_func(X) X
+#define compat_init_data
+
+#endif
+
+
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int eepro_portlist[] __initdata =
- { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360, 0};
+static unsigned int eepro_portlist[] compat_init_data =
+ { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
+/* note: 0x300 is default, the 595FX supports ALL IO Ports
+ from 0x000 to 0x3F0, some of which are reserved in PCs */
+
+/* To try the (not-really PnP Wakeup: */
+/*
+#define PnPWakeup
+*/
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
-#define NET_DEBUG 3
+#define NET_DEBUG 0
#endif
static unsigned int net_debug = NET_DEBUG;
@@ -130,23 +200,107 @@ static unsigned int net_debug = NET_DEBUG;
/* Information that need to be kept for each board. */
struct eepro_local {
- struct net_device_stats stats;
+ struct enet_statistics stats;
unsigned rx_start;
unsigned tx_start; /* start of the transmit chain */
int tx_last; /* pointer to last packet in the transmit chain */
unsigned tx_end; /* end of the transmit chain (plus 1) */
- int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10,
- FALSE = 0 for other 82595-based lan cards. */
+ int eepro; /* 1 for the EtherExpress Pro/10,
+ 2 for the EtherExpress Pro/10+,
+ 0 for other 82595-based lan cards. */
int version; /* a flag to indicate if this is a TX or FX
version of the 82595 chip. */
int stepping;
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spinlock_t lock; /* Serializing lock */
+#endif
};
/* The station (ethernet) address prefix, used for IDing the board. */
-#define SA_ADDR0 0x00
+#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */
#define SA_ADDR1 0xaa
#define SA_ADDR2 0x00
+#define GetBit(x,y) ((x & (1<<y))>>y)
+
+/* EEPROM Word 0: */
+#define ee_PnP 0 /* Plug 'n Play enable bit */
+#define ee_Word1 1 /* Word 1? */
+#define ee_BusWidth 2 /* 8/16 bit */
+#define ee_FlashAddr 3 /* Flash Address */
+#define ee_FlashMask 0x7 /* Mask */
+#define ee_AutoIO 6 /* */
+#define ee_reserved0 7 /* =0! */
+#define ee_Flash 8 /* Flash there? */
+#define ee_AutoNeg 9 /* Auto Negotiation enabled? */
+#define ee_IO0 10 /* IO Address LSB */
+#define ee_IO0Mask 0x /*...*/
+#define ee_IO1 15 /* IO MSB */
+
+/* EEPROM Word 1: */
+#define ee_IntSel 0 /* Interrupt */
+#define ee_IntMask 0x7
+#define ee_LI 3 /* Link Integrity 0= enabled */
+#define ee_PC 4 /* Polarity Correction 0= enabled */
+#define ee_TPE_AUI 5 /* PortSelection 1=TPE */
+#define ee_Jabber 6 /* Jabber prevention 0= enabled */
+#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */
+#define ee_SMOUT 8 /* SMout Pin Control 0= Input */
+#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */
+#define ee_reserved1 10 /* .. 12 =0! */
+#define ee_AltReady 13 /* Alternate Ready, 0=normal */
+#define ee_reserved2 14 /* =0! */
+#define ee_Duplex 15
+
+/* Word2,3,4: */
+#define ee_IA5 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA4 8 /*bit start for individual Addr Byte 5 */
+#define ee_IA3 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA2 8 /*bit start for individual Addr Byte 5 */
+#define ee_IA1 0 /*bit start for individual Addr Byte 5 */
+#define ee_IA0 8 /*bit start for individual Addr Byte 5 */
+
+/* Word 5: */
+#define ee_BNC_TPE 0 /* 0=TPE */
+#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
+#define ee_BootTypeMask 0x3
+#define ee_NumConn 3 /* Number of Connections 0= One or Two */
+#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */
+#define ee_PortTPE 5
+#define ee_PortBNC 6
+#define ee_PortAUI 7
+#define ee_PowerMgt 10 /* 0= disabled */
+#define ee_CP 13 /* Concurrent Processing */
+#define ee_CPMask 0x7
+
+/* Word 6: */
+#define ee_Stepping 0 /* Stepping info */
+#define ee_StepMask 0x0F
+#define ee_BoardID 4 /* Manucaturer Board ID, reserved */
+#define ee_BoardMask 0x0FFF
+
+/* Word 7: */
+#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */
+#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */
+
+/*..*/
+#define ee_SIZE 0x40 /* total EEprom Size */
+#define ee_Checksum 0xBABA /* initial and final value for adding checksum */
+
+
+/* Card identification via EEprom: */
+#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */
+#define ee_addr_id 0x11 /* Word offset for Card ID */
+#define ee_addr_SN 0x12 /* Serial Number */
+#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */
+
+
+#define ee_vendor_intel0 0x25 /* Vendor ID Intel */
+#define ee_vendor_intel1 0xD4
+#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */
+#define ee_id_eepro10p1 0x31
+
+
/* Index to functions, as function prototypes. */
extern int eepro_probe(struct device *dev);
@@ -158,15 +312,15 @@ static void eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void eepro_rx(struct device *dev);
static void eepro_transmit_interrupt(struct device *dev);
static int eepro_close(struct device *dev);
-static struct net_device_stats *eepro_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev);
+static struct enet_statistics *eepro_get_stats(struct device *dev);
+static void set_multicast_list(struct device *dev);
static int read_eeprom(int ioaddr, int location);
static void hardware_send_packet(struct device *dev, void *buf, short length);
static int eepro_grab_irq(struct device *dev);
/*
- Details of the i82595.
+ Details of the i82595.
You will need either the datasheet or the user manual to understand what
is going on here. The 82595 is very different from the 82586, 82593.
@@ -186,10 +340,10 @@ single packet. In other systems with faster computers and more congested
network traffics, the ring linked list should improve performance by
allowing up to 8K worth of packets to be queued.
-The sizes of the receive and transmit buffers can now be changed via lilo
+The sizes of the receive and transmit buffers can now be changed via lilo
or insmod. Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
where rx-buffer is in KB unit. Modules uses the parameter mem which is
-also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
+also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
The receive buffer has to be more than 3K or less than 29K. Otherwise,
it is reset to the default of 24K, and, hence, 8K for the trasnmit
buffer (transmit-buffer = 32K - receive-buffer).
@@ -197,14 +351,14 @@ buffer (transmit-buffer = 32K - receive-buffer).
*/
#define RAM_SIZE 0x8000
#define RCV_HEADER 8
-#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */
+#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */
#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */
/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */ /* 0x5ffe */
-#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)
+#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)
/* #define XMT_RAM (RAM_SIZE - RCV_RAM) */ /* 8KB for XMT buffer */
#define XMT_RAM (RAM_SIZE - (rcv_ram)) /* 8KB for XMT buffer */
/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */ /* 0x6000 */
-#define XMT_LOWER_LIMIT ((rcv_ram) >> 8)
+#define XMT_LOWER_LIMIT ((rcv_ram) >> 8)
#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8) /* 0x7ffe */
#define XMT_HEADER 8
@@ -218,9 +372,9 @@ buffer (transmit-buffer = 32K - receive-buffer).
#define XMT_CHAIN 0x04
#define XMT_COUNT 0x06
-#define BANK0_SELECT 0x00
-#define BANK1_SELECT 0x40
-#define BANK2_SELECT 0x80
+#define BANK0_SELECT 0x00
+#define BANK1_SELECT 0x40
+#define BANK2_SELECT 0x80
/* Bank 0 registers */
#define COMMAND_REG 0x00 /* Register 0 */
@@ -280,7 +434,7 @@ buffer (transmit-buffer = 32K - receive-buffer).
#define REG13 0x0d
#define FDX 0x00
#define A_N_ENABLE 0x02
-
+
#define I_ADD_REG0 0x04
#define I_ADD_REG1 0x05
#define I_ADD_REG2 0x06
@@ -295,7 +449,7 @@ buffer (transmit-buffer = 32K - receive-buffer).
#define EEDO 0x08
-/* Check for a network adaptor of this type, and return '0' iff one exists.
+/* Check for a network adaptor of this type, and return '0' if one exists.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 1, always return failure.
If dev->base_addr == 2, allocate space for the device and return success
@@ -307,19 +461,51 @@ buffer (transmit-buffer = 32K - receive-buffer).
struct netdev_entry netcard_drv =
{"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
#else
-__initfunc(int
-eepro_probe(struct device *dev))
+compat_init_func(int eepro_probe(struct device *dev))
{
int i;
int base_addr = dev ? dev->base_addr : 0;
+
+#ifdef PnPWakeup
+ /* XXXX for multiple cards should this only be run once? */
+
+ /* Wakeup: */
+ #define WakeupPort 0x279
+ #define WakeupSeq {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
+ 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
+ 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
+ 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
+
+ {
+ unsigned short int WS[32]=WakeupSeq;
+
+ if (check_region(WakeupPort, 2)==0) {
+
+ if (net_debug>5)
+ printk(KERN_DEBUG "Waking UP\n");
+
+ outb_p(0,WakeupPort);
+ outb_p(0,WakeupPort);
+ for (i=0; i<32; i++) {
+ outb_p(WS[i],WakeupPort);
+ if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
+ }
+ } else printk(KERN_WARNING "Checkregion Failed!\n");
+ }
+#endif
+
+
if (base_addr > 0x1ff) /* Check a single specified location. */
return eepro_probe1(dev, base_addr);
+
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
+
for (i = 0; eepro_portlist[i]; i++) {
int ioaddr = eepro_portlist[i];
+
if (check_region(ioaddr, EEPRO_IO_EXTENT))
continue;
if (eepro_probe1(dev, ioaddr) == 0)
@@ -330,30 +516,89 @@ eepro_probe(struct device *dev))
}
#endif
+void printEEPROMInfo(short ioaddr)
+{
+ unsigned short Word;
+ int i,j;
+
+ for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
+ j+=read_eeprom(ioaddr,i);
+ printk("Checksum: %#x\n",j&0xffff);
+
+ Word=read_eeprom(ioaddr, 0);
+ printk(KERN_DEBUG "Word0:\n");
+ printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
+ printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
+ printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg));
+ printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
+
+ if (net_debug>4) {
+ Word=read_eeprom(ioaddr, 1);
+ printk(KERN_DEBUG "Word1:\n");
+ printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
+ printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
+ printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC));
+ printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
+ printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
+ printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber));
+ printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
+ }
+
+ Word=read_eeprom(ioaddr, 5);
+ printk(KERN_DEBUG "Word5:\n");
+ printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
+ printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
+ printk(KERN_DEBUG " Has ");
+ if (GetBit(Word,ee_PortTPE)) printk("TPE ");
+ if (GetBit(Word,ee_PortBNC)) printk("BNC ");
+ if (GetBit(Word,ee_PortAUI)) printk("AUI ");
+ printk("port(s) \n");
+
+ Word=read_eeprom(ioaddr, 6);
+ printk(KERN_DEBUG "Word6:\n");
+ printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
+ printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
+
+ Word=read_eeprom(ioaddr, 7);
+ printk(KERN_DEBUG "Word7:\n");
+ printk(KERN_DEBUG " INT to IRQ:\n");
+
+ printk(KERN_DEBUG);
+
+ for (i=0, j=0; i<15; i++)
+ if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
+
+ printk("\n");
+}
+
/* This is the real probe routine. Linux has a history of friendly device
- probes on the ISA bus. A good device probes avoids doing writes, and
+ probes on the ISA bus. A good device probe avoids doing writes, and
verifies that the correct device exists and functions. */
-__initfunc(int eepro_probe1(struct device *dev, short ioaddr))
+int eepro_probe1(struct device *dev, short ioaddr)
{
unsigned short station_addr[6], id, counter;
- int i;
- int eepro; /* a flag, TRUE=1 for the EtherExpress Pro/10,
- FALSE = 0 for other 82595-based lan cards. */
+ int i,j, irqMask;
+ int eepro;
const char *ifmap[] = {"AUI", "10Base2", "10BaseT"};
enum iftype { AUI=0, BNC=1, TPE=2 };
/* Now, we are going to check for the signature of the
ID_REG (register 2 of bank 0) */
- if (((id=inb(ioaddr + ID_REG)) & ID_REG_MASK) == ID_REG_SIG) {
+ id=inb(ioaddr + ID_REG);
+
+ printk(KERN_DEBUG " id: %#x ",id);
+ printk(" io: %#x ",ioaddr);
+
+ if (((id) & ID_REG_MASK) == ID_REG_SIG) {
/* We seem to have the 82595 signature, let's
play with its counter (last 2 bits of
register 2 of bank 0) to be sure. */
-
- counter = (id & R_ROBIN_BITS);
- if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) ==
+
+ counter = (id & R_ROBIN_BITS);
+ if (((id=inb(ioaddr+ID_REG)) & R_ROBIN_BITS) ==
(counter + 0x40)) {
/* Yes, the 82595 has been found */
@@ -366,83 +611,99 @@ __initfunc(int eepro_probe1(struct device *dev, short ioaddr))
station_addr[2] = read_eeprom(ioaddr, 4);
/* Check the station address for the manufacturer's code */
-
- if (station_addr[2] != 0x00aa || (station_addr[1] & 0xff00) != 0x0000) {
- eepro = 0;
- printk("%s: Intel 82595-based lan card at %#x,",
+ if (net_debug>3)
+ printEEPROMInfo(ioaddr);
+
+ if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
+ eepro = 2;
+ printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
+ dev->name, ioaddr);
+ } else
+ if (station_addr[2] == 0x00aa) {
+ eepro = 1;
+ printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
dev->name, ioaddr);
}
else {
- eepro = 1;
- printk("%s: Intel EtherExpress Pro/10 at %#x,",
+ eepro = 0;
+ printk("%s: Intel 82595-based lan card at %#x,",
dev->name, ioaddr);
}
- /* Fill in the 'dev' fields. */
+ /* Fill in the 'dev' fields. */
dev->base_addr = ioaddr;
-
+
for (i=0; i < 6; i++) {
dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
}
-
+
if ((dev->mem_end & 0x3f) < 3 || /* RX buffer must be more than 3K */
(dev->mem_end & 0x3f) > 29) /* and less than 29K */
dev->mem_end = RCV_RAM; /* or it will be set to 24K */
else dev->mem_end = 1024*dev->mem_end; /* Maybe I should shift << 10 */
/* From now on, dev->mem_end contains the actual size of rx buffer */
-
+
if (net_debug > 3)
printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
+
+
+ /* ............... */
+
+ if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
+ dev->if_port = BNC;
+ else dev->if_port = TPE;
+
+ /* ............... */
- outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
- id = inb(ioaddr + REG3);
- if (id & TPE_BIT)
- dev->if_port = TPE;
- else dev->if_port = BNC;
- if (dev->irq < 2 && eepro) {
+ if ((dev->irq < 2) && (eepro!=0)) {
i = read_eeprom(ioaddr, 1);
- switch (i & 0x07) {
- case 0: dev->irq = 9; break;
- case 1: dev->irq = 3; break;
- case 2: dev->irq = 5; break;
- case 3: dev->irq = 10; break;
- case 4: dev->irq = 11; break;
- default: /* should never get here !!!!! */
- printk(" illegal interrupt vector stored in EEPROM.\n");
- return ENODEV;
+ irqMask = read_eeprom(ioaddr, 7);
+ i &= 0x07; /* Mask off INT number */
+
+ for (j=0; ((j<16) && (i>=0)); j++) {
+ if ((irqMask & (1<<j))!=0) {
+ if (i==0) {
+ dev->irq = j;
+ break; /* found bit corresponding to irq */
+ }
+ i--; /* count bits set in irqMask */
}
}
- else if (dev->irq == 2)
- dev->irq = 9;
+ if (dev -> irq<2) {
+ printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
+ return ENODEV;
+ } else
+
+ if (dev->irq==2) dev->irq = 9;
+ else if (dev->irq == 2)
+ dev->irq = 9;
+ }
+
if (dev->irq > 2) {
printk(", IRQ %d, %s.\n", dev->irq,
ifmap[dev->if_port]);
- if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", dev)) {
- printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
- return -EAGAIN;
- }
}
else printk(", %s.\n", ifmap[dev->if_port]);
-
+
if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */
net_debug = dev->mem_start & 7; /* still useful or not */
if (net_debug > 3) {
i = read_eeprom(ioaddr, 5);
if (i & 0x2000) /* bit 13 of EEPROM word 5 */
- printk("%s: Concurrent Processing is enabled but not used!\n",
+ printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
dev->name);
}
- if (net_debug)
+ if (net_debug)
printk(version);
/* Grab the region so we can find another board if autoIRQ fails. */
- request_region(ioaddr, EEPRO_IO_EXTENT, "eepro");
+ request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
/* Initialize the device structure */
dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
@@ -450,10 +711,13 @@ __initfunc(int eepro_probe1(struct device *dev, short ioaddr))
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct eepro_local));
- dev->open = eepro_open;
- dev->stop = eepro_close;
- dev->hard_start_xmit = eepro_send_packet;
- dev->get_stats = eepro_get_stats;
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
+#endif
+ dev->open = eepro_open;
+ dev->stop = eepro_close;
+ dev->hard_start_xmit = eepro_send_packet;
+ dev->get_stats = eepro_get_stats;
dev->set_multicast_list = &set_multicast_list;
/* Fill in the fields of the device structure with
@@ -481,21 +745,23 @@ __initfunc(int eepro_probe1(struct device *dev, short ioaddr))
*/
static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
+static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
static int eepro_grab_irq(struct device *dev)
{
- int irqlist[] = { 5, 9, 10, 11, 4, 3, 0};
+ int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
-
+
outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
/* Enable the interrupt line. */
temp_reg = inb(ioaddr + REG1);
outb(temp_reg | INT_ENABLE, ioaddr + REG1);
-
+
outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
+
/* Let EXEC event to interrupt */
outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG);
@@ -507,18 +773,17 @@ static int eepro_grab_irq(struct device *dev)
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
- if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) {
+ if (request_irq (*irqp, NULL, 0, "bogus", dev) != EBUSY) {
/* Twinkle the interrupt, and check if it's seen */
autoirq_setup(0);
outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
-
- if (*irqp == autoirq_report(2) && /* It's a good IRQ line */
- (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", dev) == 0))
- break;
+
+ if (*irqp == autoirq_report(2)) /* It's a good IRQ line */
+ break;
/* clear all interrupts */
- outb(ALL_MASK, ioaddr + STATUS_REG);
+ outb(ALL_MASK, ioaddr + STATUS_REG);
}
} while (*++irqp);
@@ -526,40 +791,64 @@ static int eepro_grab_irq(struct device *dev)
/* Disable the physical interrupt line. */
temp_reg = inb(ioaddr + REG1);
- outb(temp_reg & 0x7f, ioaddr + REG1);
+ outb(temp_reg & 0x7f, ioaddr + REG1);
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
/* Mask all the interrupts. */
- outb(ALL_MASK, ioaddr + INT_MASK_REG);
+ outb(ALL_MASK, ioaddr + INT_MASK_REG);
/* clear all interrupts */
- outb(ALL_MASK, ioaddr + STATUS_REG);
+ outb(ALL_MASK, ioaddr + STATUS_REG);
return dev->irq;
}
-static int
-eepro_open(struct device *dev)
+static int eepro_open(struct device *dev)
{
unsigned short temp_reg, old8, old9;
+ int irqMask;
int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
struct eepro_local *lp = (struct eepro_local *)dev->priv;
if (net_debug > 3)
- printk("eepro: entering eepro_open routine.\n");
+ printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
+
+ if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */
+ {
+ lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
+ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
+ }
- if (dev->dev_addr[0] == SA_ADDR0 &&
+ else if ((dev->dev_addr[0] == SA_ADDR0 &&
dev->dev_addr[1] == SA_ADDR1 &&
- dev->dev_addr[2] == SA_ADDR2)
- lp->eepro = 1; /* Yes, an Intel EtherExpress Pro/10 */
+ dev->dev_addr[2] == SA_ADDR2))
+ {
+ lp->eepro = 1;
+ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n");
+ } /* Yes, an Intel EtherExpress Pro/10 */
+
else lp->eepro = 0; /* No, it is a generic 82585 lan card */
- /* Get the interrupt vector for the 82595 */
+ /* Get the interrupt vector for the 82595 */
if (dev->irq < 2 && eepro_grab_irq(dev) == 0) {
printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
return -EAGAIN;
}
+
+ if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {
+ printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+ return -EAGAIN;
+ }
+
+#ifdef irq2dev_map
+ if (((irq2dev_map[dev->irq] != 0)
+ || (irq2dev_map[dev->irq] = dev) == 0) &&
+ (irq2dev_map[dev->irq]!=dev)) {
+ /* printk("%s: IRQ map wrong\n", dev->name); */
+ return -EAGAIN;
+ }
+#endif
/* Initialize the 82595. */
@@ -567,18 +856,18 @@ eepro_open(struct device *dev)
temp_reg = inb(ioaddr + EEPROM_REG);
lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */
-
+
if (net_debug > 3)
- printk("The stepping of the 82595 is %d\n", lp->stepping);
+ printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);
if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
outb(temp_reg & 0xef, ioaddr + EEPROM_REG);
- for (i=0; i < 6; i++)
- outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
-
+ for (i=0; i < 6; i++)
+ outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
+
temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */
outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
- | RCV_Discard_BadFrame, ioaddr + REG1);
+ | RCV_Discard_BadFrame, ioaddr + REG1);
temp_reg = inb(ioaddr + REG2); /* Match broadcast */
outb(temp_reg | 0x14, ioaddr + REG2);
@@ -589,51 +878,71 @@ eepro_open(struct device *dev)
/* Set the receiving mode */
outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
+ /* Set the interrupt vector */
+ temp_reg = inb(ioaddr + INT_NO_REG);
+ if (lp->eepro == 2)
+ outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
+ else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
+
temp_reg = inb(ioaddr + INT_NO_REG);
- outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+ if (lp->eepro == 2)
+ outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
+ else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
+ if (net_debug > 3)
+ printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
+
/* Initialize the RCV and XMT upper and lower limits */
- outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);
- outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG);
- outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG);
- outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG);
+ outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);
+ outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG);
+ outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG);
+ outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG);
/* Enable the interrupt line. */
temp_reg = inb(ioaddr + REG1);
- outb(temp_reg | INT_ENABLE, ioaddr + REG1);
+ outb(temp_reg | INT_ENABLE, ioaddr + REG1);
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
/* Let RX and TX events to interrupt */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+
/* clear all interrupts */
- outb(ALL_MASK, ioaddr + STATUS_REG);
+ outb(ALL_MASK, ioaddr + STATUS_REG);
/* Initialize RCV */
- outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR);
+ outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR);
lp->rx_start = (RCV_LOWER_LIMIT << 8) ;
- outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP);
+ outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP);
/* Initialize XMT */
- outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR);
+ outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR);
/* Check for the i82595TX and i82595FX */
old8 = inb(ioaddr + 8);
outb(~old8, ioaddr + 8);
+
if ((temp_reg = inb(ioaddr + 8)) == old8) {
if (net_debug > 3)
- printk("i82595 detected!\n");
+ printk(KERN_DEBUG "i82595 detected!\n");
lp->version = LAN595;
}
else {
lp->version = LAN595TX;
outb(old8, ioaddr + 8);
old9 = inb(ioaddr + 9);
- outb(~old9, ioaddr + 9);
- if ((temp_reg = inb(ioaddr + 9)) == ~old9) {
+ /*outb(~old9, ioaddr + 9);
+ if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) {*/
+
+ if (irqMask==ee_FX_INT2IRQ) {
enum iftype { AUI=0, BNC=1, TPE=2 };
- if (net_debug > 3)
- printk("i82595FX detected!\n");
+
+ if (net_debug > 3) {
+ printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
+ printk(KERN_DEBUG "i82595FX detected!\n");
+ }
lp->version = LAN595FX;
outb(old9, ioaddr + 9);
if (dev->if_port != TPE) { /* Hopefully, this will fix the
@@ -647,24 +956,27 @@ eepro_open(struct device *dev)
outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
}
}
- else if (net_debug > 3)
- printk("i82595TX detected!\n");
+ else if (net_debug > 3) {
+ printk(KERN_DEBUG "temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff));
+ printk(KERN_DEBUG "i82595TX detected!\n");
+ }
}
-
+
outb(SEL_RESET_CMD, ioaddr);
+
/* We are supposed to wait for 2 us after a SEL_RESET */
-
- udelay(2);
+ SLOW_DOWN;
+ SLOW_DOWN;
lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
lp->tx_last = 0;
-
+
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
if (net_debug > 3)
- printk("eepro: exiting eepro_open routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
outb(RCV_ENABLE_CMD, ioaddr);
@@ -672,36 +984,45 @@ eepro_open(struct device *dev)
return 0;
}
-static int
-eepro_send_packet(struct sk_buff *skb, struct device *dev)
+static int eepro_send_packet(struct sk_buff *skb, struct device *dev)
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
int ioaddr = dev->base_addr;
int rcv_ram = dev->mem_end;
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ unsigned long flags;
+#endif
+
if (net_debug > 5)
- printk("eepro: entering eepro_send_packet routine.\n");
-
+ printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
+
if (dev->tbusy) {
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
int tickssofar = jiffies - dev->trans_start;
if (tickssofar < 40)
return 1;
- if (net_debug > 1)
- printk("%s: transmit timed out, %s?\n", dev->name,
- "network cable problem");
+
+ /* if (net_debug > 1) */
+ printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
+ "network cable problem");
+ /* This is not a duplicate. One message for the console,
+ one for the the log file */
+ printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
+ "network cable problem");
lp->stats.tx_errors++;
/* Try to restart the adaptor. */
- outb(SEL_RESET_CMD, ioaddr);
+ outb(SEL_RESET_CMD, ioaddr);
/* We are supposed to wait for 2 us after a SEL_RESET */
- udelay(2);
+ SLOW_DOWN;
+ SLOW_DOWN;
/* Do I also need to flush the transmit buffers here? YES? */
- lp->tx_start = lp->tx_end = rcv_ram;
+ lp->tx_start = lp->tx_end = rcv_ram;
lp->tx_last = 0;
-
+
dev->tbusy=0;
dev->trans_start = jiffies;
@@ -709,84 +1030,132 @@ eepro_send_packet(struct sk_buff *skb, struct device *dev)
}
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x20155
+ /* If some higher layer thinks we've missed an tx-done interrupt
+ we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+ itself. */
+ /* if (skb == NULL) {
+ dev_tint(dev);
+ return 0;
+ }*/
+ /* according to A. Cox, this is obsolete since 1.0 */
+#endif
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_lock_irqsave(&lp->lock, flags);
+#endif
+
/* Block a timer-based transmit from overlapping. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_unlock_irqrestore(&lp->lock, flags);
+#endif
+ } else {
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
unsigned char *buf = skb->data;
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ lp->stats.tx_bytes+=skb->len;
+#endif
+
hardware_send_packet(dev, buf, length);
dev->trans_start = jiffies;
+
}
- dev_kfree_skb (skb);
+ compat_dev_kfree_skb (skb, FREE_WRITE);
/* You might need to clean up and record Tx statistics here. */
/* lp->stats.tx_aborted_errors++; */
if (net_debug > 5)
- printk("eepro: exiting eepro_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_unlock_irqrestore(&lp->lock, flags);
+#endif
+
return 0;
}
/* The typical workload of the driver:
Handle the network interface interrupts. */
+
static void
eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
- struct device *dev = dev_id;
+ struct device *dev = (struct device *)dev_id;
+ /* (struct device *)(irq2dev_map[irq]);*/
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
int ioaddr, status, boguscount = 20;
- if (net_debug > 5)
- printk("eepro: entering eepro_interrupt routine.\n");
-
if (dev == NULL) {
- printk ("eepro_interrupt(): irq %d for unknown device.\n", irq);
+ printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
+ return;
+ }
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_lock(&lp->lock);
+#endif
+
+ if (dev->interrupt) {
+ printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_unlock(&lp->lock);
+ /* FIXME : with the lock, could this ever happen ? */
+#endif
+
return;
}
dev->interrupt = 1;
+ if (net_debug > 5)
+ printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
+
ioaddr = dev->base_addr;
- do {
+ do {
status = inb(ioaddr + STATUS_REG);
-
+
if (status & RX_INT) {
if (net_debug > 4)
- printk("eepro: packet received interrupt.\n");
+ printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
/* Acknowledge the RX_INT */
outb(RX_INT, ioaddr + STATUS_REG);
-
/* Get the received packets */
eepro_rx(dev);
}
else if (status & TX_INT) {
if (net_debug > 4)
- printk("eepro: packet transmit interrupt.\n");
+ printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
/* Acknowledge the TX_INT */
- outb(TX_INT, ioaddr + STATUS_REG);
+ outb(TX_INT, ioaddr + STATUS_REG);
/* Process the status of transmitted packets */
eepro_transmit_interrupt(dev);
}
-
+
} while ((boguscount-- > 0) && (status & 0x06));
- dev->interrupt = 0;
+ dev->interrupt = 0;
+
if (net_debug > 5)
- printk("eepro: exiting eepro_interrupt routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_unlock(&lp->lock);
+#endif
return;
}
-static int
-eepro_close(struct device *dev)
+static int eepro_close(struct device *dev)
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
int ioaddr = dev->base_addr;
@@ -800,40 +1169,44 @@ eepro_close(struct device *dev)
/* Disable the physical interrupt line. */
temp_reg = inb(ioaddr + REG1);
- outb(temp_reg & 0x7f, ioaddr + REG1);
+ outb(temp_reg & 0x7f, ioaddr + REG1);
outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */
/* Flush the Tx and disable Rx. */
- outb(STOP_RCV_CMD, ioaddr);
+ outb(STOP_RCV_CMD, ioaddr);
lp->tx_start = lp->tx_end = rcv_ram ;
lp->tx_last = 0;
/* Mask all the interrupts. */
- outb(ALL_MASK, ioaddr + INT_MASK_REG);
+ outb(ALL_MASK, ioaddr + INT_MASK_REG);
/* clear all interrupts */
- outb(ALL_MASK, ioaddr + STATUS_REG);
+ outb(ALL_MASK, ioaddr + STATUS_REG);
/* Reset the 82595 */
- outb(RESET_CMD, ioaddr);
+ outb(RESET_CMD, ioaddr);
/* release the interrupt */
free_irq(dev->irq, dev);
+#ifdef irq2dev_map
+ irq2dev_map[dev->irq] = 0;
+#endif
+
/* Update the statistics here. What statistics? */
/* We are supposed to wait for 200 us after a RESET */
+ SLOW_DOWN;
+ SLOW_DOWN; /* May not be enough? */
- udelay(200);
-
MOD_DEC_USE_COUNT;
return 0;
}
/* Get the current statistics. This may be called with the card open or
closed. */
-static struct net_device_stats *
+static struct enet_statistics *
eepro_get_stats(struct device *dev)
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
@@ -851,7 +1224,7 @@ set_multicast_list(struct device *dev)
unsigned short mode;
struct dev_mc_list *dmi=dev->mc_list;
- if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63)
+ if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63)
{
/*
* We must make the kernel realise we had to move
@@ -859,17 +1232,18 @@ set_multicast_list(struct device *dev)
* the cable. If it was a promisc request the
* flag is already set. If not we assert it.
*/
- dev->flags|=IFF_PROMISC;
+ dev->flags|=IFF_PROMISC;
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
mode = inb(ioaddr + REG2);
- outb(mode | PRMSC_Mode, ioaddr + REG2);
+ outb(mode | PRMSC_Mode, ioaddr + REG2);
mode = inb(ioaddr + REG3);
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
printk("%s: promiscuous mode enabled.\n", dev->name);
}
- else if (dev->mc_count==0 )
+
+ else if (dev->mc_count==0 )
{
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
mode = inb(ioaddr + REG2);
@@ -878,11 +1252,12 @@ set_multicast_list(struct device *dev)
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
}
- else
+
+ else
{
unsigned short status, *eaddrs;
int i, boguscount = 0;
-
+
/* Disable RX and TX interrupts. Necessary to avoid
corruption of the HOST_ADDRESS_REG by interrupt
service routines. */
@@ -890,7 +1265,7 @@ set_multicast_list(struct device *dev)
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
mode = inb(ioaddr + REG2);
- outb(mode | Multi_IA, ioaddr + REG2);
+ outb(mode | Multi_IA, ioaddr + REG2);
mode = inb(ioaddr + REG3);
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
@@ -899,7 +1274,8 @@ set_multicast_list(struct device *dev)
outw(0, ioaddr + IO_PORT);
outw(0, ioaddr + IO_PORT);
outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
- for (i = 0; i < dev->mc_count; i++)
+
+ for (i = 0; i < dev->mc_count; i++)
{
eaddrs=(unsigned short *)dmi->dmi_addr;
dmi=dmi->next;
@@ -907,6 +1283,7 @@ set_multicast_list(struct device *dev)
outw(*eaddrs++, ioaddr + IO_PORT);
outw(*eaddrs++, ioaddr + IO_PORT);
}
+
eaddrs = (unsigned short *) dev->dev_addr;
outw(eaddrs[0], ioaddr + IO_PORT);
outw(eaddrs[1], ioaddr + IO_PORT);
@@ -916,9 +1293,10 @@ set_multicast_list(struct device *dev)
/* Update the transmit queue */
i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
- if (lp->tx_start != lp->tx_end)
+
+ if (lp->tx_start != lp->tx_end)
{
- /* update the next address and the chain bit in the
+ /* update the next address and the chain bit in the
last packet */
outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
outw(i, ioaddr + IO_PORT);
@@ -933,26 +1311,29 @@ set_multicast_list(struct device *dev)
/* Acknowledge that the MC setup is done */
do { /* We should be doing this in the eepro_interrupt()! */
- udelay(2);
- if (inb(ioaddr + STATUS_REG) & 0x08)
+ SLOW_DOWN;
+ SLOW_DOWN;
+ if (inb(ioaddr + STATUS_REG) & 0x08)
{
i = inb(ioaddr);
outb(0x08, ioaddr + STATUS_REG);
+
if (i & 0x20) { /* command ABORTed */
- printk("%s: multicast setup failed.\n",
+ printk("%s: multicast setup failed.\n",
dev->name);
break;
} else if ((i & 0x0f) == 0x03) { /* MC-Done */
- printk("%s: set Rx mode to %d addresses.\n",
- dev->name, dev->mc_count);
+ printk("%s: set Rx mode to %d address%s.\n",
+ dev->name, dev->mc_count,
+ dev->mc_count > 1 ? "es":"");
break;
}
}
} while (++boguscount < 100);
/* Re-enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
-
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+
}
outb(RCV_ENABLE_CMD, ioaddr);
}
@@ -961,7 +1342,7 @@ set_multicast_list(struct device *dev)
/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
/* The delay between EEPROM clock transitions. */
-#define eeprom_delay() { udelay(40); }
+#define eeprom_delay() { udelay(40); }
#define EE_READ_CMD (6 << 6)
int
@@ -972,10 +1353,10 @@ read_eeprom(int ioaddr, int location)
short ee_addr = ioaddr + EEPROM_REG;
int read_cmd = location | EE_READ_CMD;
short ctrl_val = EECS ;
-
+
outb(BANK2_SELECT, ioaddr);
outb(ctrl_val, ee_addr);
-
+
/* Shift the read command bits out. */
for (i = 8; i >= 0; i--) {
short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI
@@ -987,7 +1368,7 @@ read_eeprom(int ioaddr, int location)
eeprom_delay();
}
outb(ctrl_val, ee_addr);
-
+
for (i = 16; i > 0; i--) {
outb(ctrl_val | EESK, ee_addr); eeprom_delay();
retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
@@ -1013,18 +1394,18 @@ hardware_send_packet(struct device *dev, void *buf, short length)
unsigned status, tx_available, last, end, boguscount = 100;
if (net_debug > 5)
- printk("eepro: entering hardware_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
while (boguscount-- > 0) {
/* Disable RX and TX interrupts. Necessary to avoid
- corruption of the HOST_ADDRESS_REG by interrupt
- service routines. */
+ corruption of the HOST_ADDRESS_REG by interrupt
+ service routines. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
if (dev->interrupt == 1) {
/* Enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
continue;
}
@@ -1035,13 +1416,13 @@ hardware_send_packet(struct device *dev, void *buf, short length)
tx_available = lp->tx_start - lp->tx_end;
else tx_available = XMT_RAM;
- if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER)
+ if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER)
>= tx_available) /* No space available ??? */
{
eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
/* Enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
continue;
}
@@ -1049,17 +1430,20 @@ hardware_send_packet(struct device *dev, void *buf, short length)
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */
- if ((RAM_SIZE - last) <= XMT_HEADER) {
- /* Arrrr!!!, must keep the xmt header together,
- several days were lost to chase this one down. */
+
+ if ((RAM_SIZE - last) <= XMT_HEADER) {
+ /* Arrrr!!!, must keep the xmt header together,
+ several days were lost to chase this one down. */
+
last = rcv_ram;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
}
+
else end = rcv_ram + (end - RAM_SIZE);
}
outw(last, ioaddr + HOST_ADDRESS_REG);
- outw(XMT_CMD, ioaddr + IO_PORT);
+ outw(XMT_CMD, ioaddr + IO_PORT);
outw(0, ioaddr + IO_PORT);
outw(end, ioaddr + IO_PORT);
outw(length, ioaddr + IO_PORT);
@@ -1074,22 +1458,24 @@ hardware_send_packet(struct device *dev, void *buf, short length)
}
/* A dummy read to flush the DRAM write pipeline */
- status = inw(ioaddr + IO_PORT);
+ status = inw(ioaddr + IO_PORT);
- if (lp->tx_start == lp->tx_end) {
+ if (lp->tx_start == lp->tx_end) {
outw(last, ioaddr + XMT_BAR);
outb(XMT_CMD, ioaddr);
lp->tx_start = last; /* I don't like to change tx_start here */
}
else {
- /* update the next address and the chain bit in the
- last packet */
+ /* update the next address and the chain bit in the
+ last packet */
+
if (lp->tx_end != last) {
outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
- outw(last, ioaddr + IO_PORT);
+ outw(last, ioaddr + IO_PORT);
}
+
outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
- status = inw(ioaddr + IO_PORT);
+ status = inw(ioaddr + IO_PORT);
outw(status | CHAIN_BIT, ioaddr + IO_PORT);
/* Continue the transmit command */
@@ -1099,23 +1485,21 @@ hardware_send_packet(struct device *dev, void *buf, short length)
lp->tx_last = last;
lp->tx_end = end;
- /* Enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
-
if (dev->tbusy) {
dev->tbusy = 0;
}
-
- lp->stats.tx_bytes += length;
+
+ /* Enable RX and TX interrupts */
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
if (net_debug > 5)
- printk("eepro: exiting hardware_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
return;
}
dev->tbusy = 1;
if (net_debug > 5)
- printk("eepro: exiting hardware_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
}
static void
@@ -1128,25 +1512,31 @@ eepro_rx(struct device *dev)
unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
if (net_debug > 5)
- printk("eepro: entering eepro_rx routine.\n");
-
+ printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
+
/* Set the read pointer to the start of the RCV */
outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
+
rcv_event = inw(ioaddr + IO_PORT);
while (rcv_event == RCV_DONE) {
- rcv_status = inw(ioaddr + IO_PORT);
+
+ rcv_status = inw(ioaddr + IO_PORT);
rcv_next_frame = inw(ioaddr + IO_PORT);
- rcv_size = inw(ioaddr + IO_PORT);
+ rcv_size = inw(ioaddr + IO_PORT);
if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
+
/* Malloc up new buffer. */
struct sk_buff *skb;
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ lp->stats.rx_bytes+=rcv_size;
+#endif
rcv_size &= 0x3fff;
skb = dev_alloc_skb(rcv_size+5);
if (skb == NULL) {
- printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
break;
}
@@ -1155,33 +1545,39 @@ eepro_rx(struct device *dev)
if (lp->version == LAN595)
insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
- else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
+ else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
unsigned short temp = inb(ioaddr + INT_MASK_REG);
outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
- insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), (rcv_size + 3) >> 2);
+ insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
+ (rcv_size + 3) >> 2);
outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
}
-
-
- skb->protocol = eth_type_trans(skb,dev);
+
+ skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
lp->stats.rx_packets++;
- lp->stats.rx_bytes += rcv_size;
}
- else { /* Not sure will ever reach here,
- I set the 595 to discard bad received frames */
+
+ else { /* Not sure will ever reach here,
+ I set the 595 to discard bad received frames */
lp->stats.rx_errors++;
+
if (rcv_status & 0x0100)
lp->stats.rx_over_errors++;
+
else if (rcv_status & 0x0400)
lp->stats.rx_frame_errors++;
+
else if (rcv_status & 0x0800)
lp->stats.rx_crc_errors++;
- printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
+
+ printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
}
+
if (rcv_status & 0x1000)
lp->stats.rx_length_errors++;
+
if (--boguscount == 0)
break;
@@ -1190,13 +1586,14 @@ eepro_rx(struct device *dev)
outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
rcv_event = inw(ioaddr + IO_PORT);
- }
+ }
if (rcv_car == 0)
rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+
outw(rcv_car - 1, ioaddr + RCV_STOP);
if (net_debug > 5)
- printk("eepro: exiting eepro_rx routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
}
static void
@@ -1204,33 +1601,47 @@ eepro_transmit_interrupt(struct device *dev)
{
struct eepro_local *lp = (struct eepro_local *)dev->priv;
short ioaddr = dev->base_addr;
- short boguscount = 20;
+ short boguscount = 20;
short xmt_status;
+
+ /*
+ if (dev->tbusy == 0) {
+ printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
+ dev->name);
+ printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
+ dev->name);
+ }
+ */
- while (lp->tx_start != lp->tx_end) {
-
- outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
+ while (lp->tx_start != lp->tx_end) {
+
+ outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
xmt_status = inw(ioaddr+IO_PORT);
+
if ((xmt_status & TX_DONE_BIT) == 0) break;
- xmt_status = inw(ioaddr+IO_PORT);
+ xmt_status = inw(ioaddr+IO_PORT);
lp->tx_start = inw(ioaddr+IO_PORT);
dev->tbusy = 0;
mark_bh(NET_BH);
if (xmt_status & 0x2000)
- lp->stats.tx_packets++;
+ lp->stats.tx_packets++;
else {
lp->stats.tx_errors++;
if (xmt_status & 0x0400)
lp->stats.tx_carrier_errors++;
printk("%s: XMT status = %#x\n",
dev->name, xmt_status);
+ printk(KERN_DEBUG "%s: XMT status = %#x\n",
+ dev->name, xmt_status);
}
+
if (xmt_status & 0x000f) {
lp->stats.collisions += (xmt_status & 0x000f);
}
+
if ((xmt_status & 0x0040) == 0x0) {
lp->stats.tx_heartbeat_errors++;
}
@@ -1241,43 +1652,76 @@ eepro_transmit_interrupt(struct device *dev)
}
#ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_eepro = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, eepro_probe };
-static int io = 0x200;
-static int irq = 0;
-static int mem = (RCV_RAM/1024); /* Size of the rx buffer in KB */
+#define MAX_EEPRO 8
+static char devicename[MAX_EEPRO][9];
+static struct device dev_eepro[MAX_EEPRO];
+static int io[MAX_EEPRO] = {
+#ifdef PnPWakeup
+ 0x210, /*: default for PnP enabled FX chips */
+#else
+ 0x200, /* Why? */
+#endif
+ -1, -1, -1, -1, -1, -1, -1};
+static int irq[MAX_EEPRO] = {0, 0, 0, 0, 0, 0, 0, 0};
+static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */
+ (RCV_RAM/1024),
+ (RCV_RAM/1024),
+ (RCV_RAM/1024),
+ (RCV_RAM/1024),
+ (RCV_RAM/1024),
+ (RCV_RAM/1024),
+ (RCV_RAM/1024),
+ (RCV_RAM/1024)
+};
+
+static int n_eepro = 0;
+/* For linux 2.1.xx */
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+MODULE_AUTHOR("Pascal Dupuis <dupuis@lei.ucl.ac.be> for the 2.1 stuff (locking,...)");
+MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
MODULE_PARM(mem, "i");
+#endif
-int
+int
init_module(void)
{
- if (io == 0)
- printk("eepro: You should not use auto-probing with insmod!\n");
- dev_eepro.base_addr = io;
- dev_eepro.irq = irq;
- dev_eepro.mem_end = mem;
-
- if (register_netdev(&dev_eepro) != 0)
- return -EIO;
- return 0;
+ if (io[0] == 0)
+ printk("eepro_init_module: You should not use auto-probing with insmod!\n");
+
+ while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
+ struct device *d = &dev_eepro[n_eepro];
+ d->name = devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
+ d->mem_end = mem[n_eepro];
+ d->base_addr = io[n_eepro];
+ d->irq = irq[n_eepro];
+ d->init = eepro_probe;
+
+ if (register_netdev(d) == 0)
+ n_eepro++;
+ }
+
+ return n_eepro ? 0 : -ENODEV;
}
void
cleanup_module(void)
{
- unregister_netdev(&dev_eepro);
- kfree_s(dev_eepro.priv,sizeof(struct eepro_local));
- dev_eepro.priv=NULL;
+ int i;
+
+ for (i=0; i<n_eepro; i++) {
+ struct device *d = &dev_eepro[i];
+ unregister_netdev(d);
+
+ kfree_s(d->priv,sizeof(struct eepro_local));
+ d->priv=NULL;
- /* If we don't do this, we can't re-insmod it later. */
- release_region(dev_eepro.base_addr, EEPRO_IO_EXTENT);
+ /* If we don't do this, we can't re-insmod it later. */
+ release_region(d->base_addr, EEPRO_IO_EXTENT);
+
+ }
}
#endif /* MODULE */
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 14354fd1a..94546d995 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -1110,6 +1110,7 @@ static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
/* Free the original skb. */
if (sp->tx_skbuff[entry]) {
sp->stats.tx_packets++; /* Count only user packets. */
+ sp->stats.tx_bytes += sp->tx_skbuff[entry]->len; /* Count transmitted bytes */
dev_free_skb(sp->tx_skbuff[entry]);
sp->tx_skbuff[entry] = 0;
} else if ((sp->tx_ring[entry].status&0x70000) == CmdNOp << 16)
@@ -1228,6 +1229,7 @@ speedo_rx(struct device *dev)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
sp->stats.rx_packets++;
+ sp->stats.rx_bytes += pkt_len; /* Count received bytes */
}
entry = (++sp->cur_rx) % RX_RING_SIZE;
}
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 057fe5b86..005c574df 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -97,6 +97,7 @@
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
+#include <asm/irq.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -506,7 +507,7 @@ static int eexp_xmit(struct sk_buff *buf, struct device *dev)
printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
#endif
- outb(SIRQ_dis|irqrmap[dev->irq],dev->base_addr+SET_IRQ);
+ disable_irq(dev->irq);
/* If dev->tbusy is set, all our tx buffers are full but the kernel
* is calling us anyway. Check that nothing bad is happening.
@@ -543,7 +544,7 @@ static int eexp_xmit(struct sk_buff *buf, struct device *dev)
eexp_hw_tx_pio(dev,data,length);
}
dev_kfree_skb(buf);
- outb(SIRQ_en|irqrmap[dev->irq],dev->base_addr+SET_IRQ);
+ enable_irq(dev->irq);
return 0;
}
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index dc52fd84e..e56ddf5b0 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -1,25 +1,24 @@
-/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Linux. */
+/* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
/*
- NOTICE: THIS IS THE ALPHA TEST VERSION!
- Written 1997 by Donald Becker.
+ Written/copyright 1997-1998 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
- All other rights reserved.
+ All other rights reserved.
- This driver is for the SMC EtherPower II 9432 PCI ethernet adapter based on
- the SMC83c170.
+ This driver is for the SMC83c170/175 "EPIC" series, as used on the
+ SMC EtherPower II 9432 PCI adapter, and several CardBus cards.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
- Center of Excellence in Space Data and Information Sciences
+ USRA Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
- Support and updates available at
+ Information and updates available at
http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html
*/
static const char *version =
-"epic100.c:v0.10 10/14/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+"epic100.c:v1.04 8/23/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
/* A few user-configurable values. */
@@ -32,7 +31,7 @@ static const char *version =
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1518 effectively disables this feature. */
-static const int rx_copybreak = 200;
+static int rx_copybreak = 200;
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 10;
@@ -44,35 +43,38 @@ static int max_interrupt_work = 10;
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
/* Bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
+#define TX_FIFO_THRESH 256 /* Rounded down to 4 byte units. */
#define RX_FIFO_THRESH 1 /* 0-3, 0==32, 64,96, or 3==128 bytes */
-#include <linux/config.h>
+#include <linux/version.h> /* Evil, but neccessary */
#ifdef MODULE
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>
-#include <linux/version.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#endif
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/string.h>
#include <linux/timer.h>
-#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#if LINUX_VERSION_CODE >= 0x20155
+#define PCI_SUPPORT_VER2
+#else
+#include <linux/bios32.h>
+#endif
+#include <linux/delay.h>
+
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
-#include <asm/dma.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -80,70 +82,39 @@ static int max_interrupt_work = 10;
/* Kernel compatibility defines, common to David Hind's PCMCIA package.
This is only in the support-all-kernels source code. */
-#include <linux/version.h> /* Evil, but neccessary */
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x) /* What to put in timer->expires. */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#define virt_to_bus(addr) ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-
-#else /* 1.3.0 and later */
-#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
-#endif
-
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
-#ifdef MODULE
-#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
-char kernel_version[] = UTS_RELEASE;
-#endif
-#else
-#undef MOD_INC_USE_COUNT
-#define MOD_INC_USE_COUNT
-#undef MOD_DEC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-#endif /* 1.3.38 */
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
-#include <linux/delay.h>
+#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000
+#warning This driver version is only for kernel versions 2.0.0 and later.
#endif
-#ifdef SA_SHIRQ
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#else
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
-#endif
+#define RUN_AT(x) (jiffies + (x))
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#include <linux/bios32.h>
-#else
-#ifdef MODULE
+#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("SMC 82c170 EPIC series Ethernet driver");
+MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
MODULE_PARM(debug, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
MODULE_PARM(rx_copybreak, "i");
MODULE_PARM(max_interrupt_work, "i");
#endif
+#if LINUX_VERSION_CODE < 0x20123
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#endif
+#if LINUX_VERSION_CODE <= 0x20139
+#define net_device_stats enet_statistics
+#define NETSTATS_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20159
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
+#else /* Grrr, unneeded incompatible change. */
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
#endif
/* The I/O extent. */
#define EPIC_TOTAL_SIZE 0x100
-#ifdef HAVE_DEVLIST
-struct netdev_entry epic100_drv =
-{"Epic100", epic100_pci_probe, EPIC_TOTAL_SIZE, NULL};
-#endif
-
+#define epic_debug debug
static int epic_debug = 1;
/*
@@ -151,11 +122,10 @@ static int epic_debug = 1;
I. Board Compatibility
-This device driver is designed for the SMC "EPCI/100", the SMC
-single-chip ethernet controllers for PCI. This chip is used on
+This device driver is designed for the SMC "EPIC/100", the SMC
+single-chip Ethernet controllers for PCI. This chip is used on
the SMC EtherPower II boards.
-
II. Board-specific settings
PCI bus devices are configured by the system at boot time, so no jumpers
@@ -170,25 +140,44 @@ IIIa. Ring buffers
IVb. References
-http://www.smc.com/components/catalog/smc83c170.html
+http://www.smsc.com/main/datasheets/83c171.pdf
+http://www.smsc.com/main/datasheets/83c175.pdf
http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.national.com/pf/DP/DP83840.html
+http://www.national.com/pf/DP/DP83840A.html
IVc. Errata
*/
-#ifndef PCI_VENDOR_ID_SMC
-#define PCI_VENDOR_ID_SMC 0x10B8
-#endif
-#ifndef PCI_DEVICE_ID_SMC_EPIC100
-#define PCI_DEVICE_ID_SMC_EPIC100 0x0005
-#endif
-
/* The rest of these values should never change. */
+
+static struct device *epic_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr, int irq,
+ int chip_id, int card_idx);
+
+enum pci_flags_bit {
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+
+struct chip_info {
+ const char *name;
+ u16 vendor_id, device_id, device_id_mask, pci_flags;
+ int io_size, min_latency;
+ struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+ long ioaddr, int irq, int chip_idx, int fnd_cnt);
+} chip_tbl[] = {
+ {"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
+ PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+ {"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff,
+ PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+ {0,},
+};
+
/* Offsets to registers, using the (ugh) SMC names. */
enum epic_registers {
COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
+ PCIBurstCnt=0x18,
TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28, /* Rx error counters. */
MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
LAN0=64, /* MAC address. */
@@ -199,8 +188,9 @@ enum epic_registers {
/* Interrupt register bits, using my own meaningful names. */
enum IntrStatus {
- TxIdle=0x40000, RxIdle=0x20000,
- CntFull=0x0200, TxUnderrun=0x0100,
+ TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
+ PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
+ RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
};
@@ -213,7 +203,7 @@ struct epic_tx_desc {
u32 bufaddr;
u16 buflength;
u16 control;
- u32 next;
+ u32 next;
};
struct epic_rx_desc {
@@ -221,29 +211,36 @@ struct epic_rx_desc {
u16 rxlength;
u32 bufaddr;
u32 buflength;
- u32 next;
+ u32 next;
};
struct epic_private {
char devname[8]; /* Used only for kernel debugging. */
const char *product_name;
struct device *next_module;
+
+ /* Tx and Rx rings here so that they remain paragraph aligned. */
struct epic_rx_desc rx_ring[RX_RING_SIZE];
struct epic_tx_desc tx_ring[TX_RING_SIZE];
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
/* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
- int chip_id;
- int revision;
- struct enet_statistics stats;
- struct timer_list timer; /* Media selection timer. */
+
+ /* Ring pointers. */
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
+
+ u8 pci_bus, pci_dev_fn; /* PCI bus location. */
+ u16 chip_id;
+
+ struct net_device_stats stats;
+ struct timer_list timer; /* Media selection timer. */
unsigned char mc_filter[8];
signed char phys[4]; /* MII device addresses. */
unsigned int tx_full:1; /* The Tx queue is full. */
- unsigned int full_duplex:1; /* Full-duplex operation requested. */
+ unsigned int full_duplex:1; /* Current duplex setting. */
+ unsigned int force_fd:1; /* Full-duplex operation requested. */
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int media2:4; /* Secondary monitored media port. */
unsigned int medialock:1; /* Don't sense media type. */
@@ -251,162 +248,174 @@ struct epic_private {
int pad0, pad1; /* Used for 8-byte alignment */
};
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#ifdef MODULE
/* Used to pass the full-duplex flag, etc. */
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#endif
+#define MAX_UNITS 8
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
- int chip_id, int options, int card_idx);
static int epic_open(struct device *dev);
-static int read_eeprom(int ioaddr, int location);
-static int mii_read(int ioaddr, int phy_id, int location);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
+static void epic_restart(struct device *dev);
static void epic_timer(unsigned long data);
static void epic_tx_timeout(struct device *dev);
static void epic_init_ring(struct device *dev);
static int epic_start_xmit(struct sk_buff *skb, struct device *dev);
static int epic_rx(struct device *dev);
static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
static int epic_close(struct device *dev);
-static struct enet_statistics *epic_get_stats(struct device *dev);
-#ifdef NEW_MULTICAST
+static struct net_device_stats *epic_get_stats(struct device *dev);
static void set_rx_mode(struct device *dev);
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
-
-#ifdef MODULE
/* A list of all installed EPIC devices, for removing the driver module. */
static struct device *root_epic_dev = NULL;
-#endif
+#ifndef CARDBUS
int epic100_probe(struct device *dev)
{
int cards_found = 0;
- static int pci_index = 0; /* Static, for multiple probe calls. */
-
- /* Ideally we would detect all network cards in slot order. That would
- be best done a central PCI probe dispatch, which wouldn't work
- well with the current structure. So instead we detect just the
- Epic cards in slot order. */
+ int chip_idx, irq;
+ u16 pci_command, new_command;
+ unsigned char pci_bus, pci_device_fn;
+
+#ifdef PCI_SUPPORT_VER2
+ struct pci_dev *pcidev = NULL;
+ while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
+ != NULL) {
+ long pci_ioaddr = pcidev->base_address[0] & ~3;
+ int vendor = pcidev->vendor;
+ int device = pcidev->device;
+
+ for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor == chip_tbl[chip_idx].vendor_id
+ && (device & chip_tbl[chip_idx].device_id_mask) ==
+ chip_tbl[chip_idx].device_id)
+ break;
+ if (chip_tbl[chip_idx].vendor_id == 0 /* Compiled out! */
+ || check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+ continue;
+ pci_bus = pcidev->bus->number;
+ pci_device_fn = pcidev->devfn;
+ irq = pcidev->irq;
+#else
+ int pci_index;
- if (pci_present()) {
- unsigned char pci_bus, pci_device_fn;
+ if ( ! pcibios_present())
+ return -ENODEV;
- for (;pci_index < 0xff; pci_index++) {
-#if LINUX_VERSION_CODE >= 0x20155
- unsigned int pci_irq_line;
- struct pci_dev *pdev;
-#else
- unsigned char pci_irq_line;
-#endif
- unsigned char pci_latency;
- unsigned short pci_command, vendor, device;
- unsigned int pci_ioaddr, chip_idx = 0;
+ for (pci_index = 0; pci_index < 0xff; pci_index++) {
+ u8 pci_irq_line;
+ u16 vendor, device;
+ u32 pci_ioaddr;
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-#ifdef REVERSE_PROBE_ORDER
- 0xff - pci_index,
-#else
- pci_index,
-#endif
- &pci_bus, &pci_device_fn)
- != PCIBIOS_SUCCESSFUL)
+ if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+ pci_index, &pci_bus, &pci_device_fn)
+ != PCIBIOS_SUCCESSFUL)
+ break;
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_DEVICE_ID, &device);
+
+ for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor == chip_tbl[chip_idx].vendor_id
+ && (device & chip_tbl[chip_idx].device_id_mask) ==
+ chip_tbl[chip_idx].device_id)
break;
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- if (vendor != PCI_VENDOR_ID_SMC)
- continue;
-
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
-#if LINUX_VERSION_CODE >= 0x20155
- pdev = pci_find_slot(pci_bus, pci_device_fn);
- pci_irq_line = pdev->irq;
- pci_ioaddr = pdev->base_address[0];
-#else
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ if (chip_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
+ continue;
+
+ pcibios_read_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ /* Remove I/O space marker in bit 0. */
+ pci_ioaddr &= ~3;
+ irq = pci_irq_line;
+
+ if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+ continue;
#endif
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
-
- if (device != PCI_DEVICE_ID_SMC_EPIC100) {
- printk("Unknown SMC PCI ethernet chip type %4.4x detected:"
- " not configured.\n", device);
- continue;
- }
- if (epic_debug > 2)
- printk("Found SMC PCI EPIC/100 at I/O %#x, IRQ %d.\n",
- pci_ioaddr, pci_irq_line);
- if (check_region(pci_ioaddr, EPIC_TOTAL_SIZE))
- continue;
+ /* EPIC-specific code: Soft-reset the chip ere setting as master. */
+ outl(0x0001, pci_ioaddr + GENCTL);
+
+ /* Activate the card: fix for brain-damaged Win98 BIOSes. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, &pci_command);
+ new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+ if (pci_command != new_command) {
+ printk(KERN_INFO " The PCI BIOS has not enabled Ethernet"
+ " device %4.4x-%4.4x."
+ " Updating PCI command %4.4x->%4.4x.\n",
+ vendor, device, pci_command, new_command);
+ pcibios_write_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, new_command);
+ }
-#ifdef MODULE
- dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
- options[cards_found], cards_found);
-#else
- dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
- dev ? dev->mem_start : 0, -1);
-#endif
+ dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr,
+ irq, chip_idx, cards_found);
- if (dev) {
- /* Get and check the bus-master and latency values. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
- if ( ! (pci_command & PCI_COMMAND_MASTER)) {
- printk(" PCI Master Bit has not been set! Setting...\n");
- pci_command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, pci_command);
- }
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 10) {
- printk(" PCI latency timer (CFLT) is unreasonably low at %d."
- " Setting to 255 clocks.\n", pci_latency);
+ /* Check the latency timer. */
+ if (dev) {
+ u8 pci_latency;
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_LATENCY_TIMER, &pci_latency);
+ if (pci_latency < chip_tbl[chip_idx].min_latency) {
+ printk(KERN_INFO " PCI latency timer (CFLT) value of %d is "
+ "unreasonably low, setting to %d.\n", pci_latency,
+ chip_tbl[chip_idx].min_latency);
pcibios_write_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, 255);
- } else if (epic_debug > 1)
- printk(" PCI latency timer (CFLT) is %#x.\n", pci_latency);
- dev = 0;
- cards_found++;
+ PCI_LATENCY_TIMER,
+ chip_tbl[chip_idx].min_latency);
}
+ dev = 0;
+ cards_found++;
}
}
-#if defined (MODULE)
- return cards_found;
-#else
return cards_found ? 0 : -ENODEV;
-#endif
}
+#endif /* not CARDBUS */
-static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
- int chip_id, int options, int card_idx)
+static struct device *epic_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr, int irq,
+ int chip_idx, int card_idx)
{
- static int did_version = 0; /* Already printed version info. */
- struct epic_private *tp;
- int i;
-
- if (epic_debug > 0 && did_version++ == 0)
- printk(version);
+ struct epic_private *ep;
+ int i, option = 0, duplex = 0;
+
+ if (dev && dev->mem_start) {
+ option = dev->mem_start;
+ duplex = (dev->mem_start & 16) ? 1 : 0;
+ } else if (card_idx >= 0 && card_idx < MAX_UNITS) {
+ if (options[card_idx] >= 0)
+ option = options[card_idx];
+ if (full_duplex[card_idx] >= 0)
+ duplex = full_duplex[card_idx];
+ }
dev = init_etherdev(dev, 0);
- printk("%s: SMC EPIC/100 at %#3x, IRQ %d, ", dev->name, ioaddr, irq);
+ dev->base_addr = ioaddr;
+ dev->irq = irq;
+ printk(KERN_INFO "%s: SMC EPIC/100 at %#lx, IRQ %d, ",
+ dev->name, ioaddr, dev->irq);
/* Bring the chip out of low-power mode. */
- outl(0x0200, ioaddr + GENCTL);
+ outl(0x4200, ioaddr + GENCTL);
/* Magic?! If we don't set this bit the MII interface won't work. */
outl(0x0008, ioaddr + TEST1);
+ /* Turn on the MII transceiver. */
+ outl(0x12, ioaddr + MIICfg);
+ if (chip_idx == 1)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ outl(0x0200, ioaddr + GENCTL);
+
/* This could also be read from the EEPROM. */
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
@@ -416,65 +425,68 @@ static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
printk("%2.2x.\n", dev->dev_addr[i]);
if (epic_debug > 1) {
- printk("%s: EEPROM contents\n", dev->name);
- for (i = 0; i < 64; i++)
- printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : "");
+ printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
+ for (i = 0; i < 64; i++)
+ printk(" %4.4x%s", read_eeprom(ioaddr, i),
+ i % 16 == 15 ? "\n" : "");
}
/* We do a request_region() to register /proc/ioports info. */
- request_region(ioaddr, EPIC_TOTAL_SIZE, "SMC EPIC/100");
-
- dev->base_addr = ioaddr;
- dev->irq = irq;
+ request_region(ioaddr, EPIC_TOTAL_SIZE, dev->name);
/* The data structures must be quadword aligned. */
- tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
- memset(tp, 0, sizeof(*tp));
- dev->priv = tp;
+ ep = kmalloc(sizeof(*ep), GFP_KERNEL | GFP_DMA);
+ memset(ep, 0, sizeof(*ep));
+ dev->priv = ep;
-#ifdef MODULE
- tp->next_module = root_epic_dev;
+ ep->next_module = root_epic_dev;
root_epic_dev = dev;
-#endif
- tp->chip_id = chip_id;
+ ep->pci_bus = pci_bus;
+ ep->pci_dev_fn = pci_devfn;
+#if defined(PCI_SUPPORT_VER2)
+ ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device;
+#else
+ ep->chip_id = chip_tbl[chip_idx].device_id;
+#endif
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later, but
takes too much time. */
{
int phy, phy_idx;
- for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+ for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys);
phy++) {
- int mii_status = mii_read(ioaddr, phy, 0);
+ int mii_status = mdio_read(ioaddr, phy, 1);
if (mii_status != 0xffff && mii_status != 0x0000) {
- tp->phys[phy_idx++] = phy;
- printk("%s: MII transceiver found at address %d.\n",
- dev->name, phy);
+ ep->phys[phy_idx++] = phy;
+ printk(KERN_INFO "%s: MII transceiver #%d control "
+ "%4.4x status %4.4x.\n"
+ KERN_INFO "%s: Autonegotiation advertising %4.4x "
+ "link partner %4.4x.\n",
+ dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status,
+ dev->name, mdio_read(ioaddr, phy, 4),
+ mdio_read(ioaddr, phy, 5));
}
}
if (phy_idx == 0) {
- printk("%s: ***WARNING***: No MII transceiver found!\n",
+ printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
dev->name);
/* Use the known PHY address of the EPII. */
- tp->phys[0] = 3;
+ ep->phys[0] = 3;
}
}
- /* Leave the chip in low-power mode. */
+ /* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
+ if (ep->chip_id == 6)
+ outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
outl(0x0008, ioaddr + GENCTL);
/* The lower four bits are the media type. */
- if (options > 0) {
- tp->full_duplex = (options & 16) ? 1 : 0;
- tp->default_port = options & 15;
- if (tp->default_port)
- tp->medialock = 1;
- }
- if (card_idx >= 0) {
- if (full_duplex[card_idx] >= 0)
- tp->full_duplex = full_duplex[card_idx];
- }
+ ep->force_fd = duplex;
+ ep->default_port = option;
+ if (ep->default_port)
+ ep->medialock = 1;
/* The Epic-specific entries in the device structure. */
dev->open = &epic_open;
@@ -482,6 +494,7 @@ static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
dev->stop = &epic_close;
dev->get_stats = &epic_get_stats;
dev->set_multicast_list = &set_rx_mode;
+ dev->do_ioctl = &mii_ioctl;
return dev;
}
@@ -498,41 +511,42 @@ static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
#define EE_ENB (0x0001 | EE_CS)
/* Delay between EEPROM clock transitions.
- The 1.2 code is a "nasty" timing loop, but PC compatible machines are
- *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro. */
+ No extra delay is needed with 33Mhz PCI, but 66Mhz is untested.
+ */
+
#ifdef _LINUX_DELAY_H
-#define eeprom_delay(nanosec) udelay((nanosec + 999)/1000)
+#define eeprom_delay(nanosec) udelay(1)
#else
-#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#define eeprom_delay(nanosec) do { ; } while (0)
#endif
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
-#define EE_READ_CMD (6 << 6)
+#define EE_READ64_CMD (6 << 6)
+#define EE_READ256_CMD (6 << 8)
#define EE_ERASE_CMD (7 << 6)
-static int read_eeprom(int ioaddr, int location)
+static int read_eeprom(long ioaddr, int location)
{
int i;
int retval = 0;
- int ee_addr = ioaddr + EECTL;
- int read_cmd = location | EE_READ_CMD;
-
+ long ee_addr = ioaddr + EECTL;
+ int read_cmd = location |
+ (inl(ee_addr) & 0x40) ? EE_READ64_CMD : EE_READ256_CMD;
+
outl(EE_ENB & ~EE_CS, ee_addr);
outl(EE_ENB, ee_addr);
-
+
/* Shift the read command bits out. */
- for (i = 10; i >= 0; i--) {
- short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+ for (i = 12; i >= 0; i--) {
+ short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
outl(EE_ENB | dataval, ee_addr);
eeprom_delay(100);
outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(150);
- outl(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */
- eeprom_delay(250);
}
outl(EE_ENB, ee_addr);
-
+
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay(100);
@@ -548,7 +562,7 @@ static int read_eeprom(int ioaddr, int location)
#define MII_READOP 1
#define MII_WRITEOP 2
-static int mii_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
{
int i;
@@ -556,66 +570,82 @@ static int mii_read(int ioaddr, int phy_id, int location)
/* Typical operation takes < 50 ticks. */
for (i = 4000; i > 0; i--)
if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0)
+ return inw(ioaddr + MIIData);
+ return 0xffff;
+}
+
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
+{
+ int i;
+
+ outw(value, ioaddr + MIIData);
+ outl((phy_id << 9) | (location << 4) | MII_WRITEOP, ioaddr + MIICtrl);
+ for (i = 10000; i > 0; i--) {
+ if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
break;
- return inw(ioaddr + MIIData);
+ }
+ return;
}
static int
epic_open(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
int i;
int mii_reg5;
- int full_duplex = 0;
+ ep->full_duplex = ep->force_fd;
/* Soft reset the chip. */
- outl(0x0001, ioaddr + GENCTL);
+ outl(0x4001, ioaddr + GENCTL);
-#ifdef SA_SHIRQ
- if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ,
- "SMC EPIC/100", dev)) {
- return -EAGAIN;
- }
-#else
- if (irq2dev_map[dev->irq] != NULL
- || (irq2dev_map[dev->irq] = dev) == NULL
- || dev->irq == 0
- || request_irq(dev->irq, &epic_interrupt, 0, "SMC EPIC/100")) {
+ if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
return -EAGAIN;
- }
-#endif
MOD_INC_USE_COUNT;
epic_init_ring(dev);
- /* This next line by Ken Yamaguchi.. ?? */
- outl(0x8, ioaddr + 0x1c);
+ outl(0x4000, ioaddr + GENCTL);
+ /* This next magic! line by Ken Yamaguchi.. ?? */
+ outl(0x0008, ioaddr + TEST1);
- /* Pull the chip out of low-power mode, enable interrupts, and set for PCI read multiple. */
+ /* Pull the chip out of low-power mode, enable interrupts, and set for
+ PCI read multiple. The MIIcfg setting and strange write order are
+ required by the details of which bits are reset and the transceiver
+ wiring on the Ositech CardBus card.
+ */
+ outl(0x12, ioaddr + MIICfg);
+ if (ep->chip_id == 6)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+
+#if defined(__powerpc__) || defined(__sparc__) /* Big endian */
+ outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#else
outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#endif
for (i = 0; i < 3; i++)
outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
outl(TX_FIFO_THRESH, ioaddr + TxThresh);
- full_duplex = tp->full_duplex;
- mii_reg5 = mii_read(ioaddr, tp->phys[0], 5);
- if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
- full_duplex = 1;
+ mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+ if (mii_reg5 != 0xffff) {
+ if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
+ ep->full_duplex = 1;
+ else if (! (mii_reg5 & 0x4000))
+ mdio_write(ioaddr, ep->phys[0], 0, 0x1200);
if (epic_debug > 1)
- printk("%s: Setting %s-duplex based on MII xcvr %d"
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
" register read of %4.4x.\n", dev->name,
- full_duplex ? "full" : "half", tp->phys[0],
- mii_read(ioaddr, tp->phys[0], 5));
+ ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
}
- outl(full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
- outl(virt_to_bus(tp->rx_ring), ioaddr + PRxCDAR);
- outl(virt_to_bus(tp->tx_ring), ioaddr + PTxCDAR);
+ outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ outl(virt_to_bus(ep->rx_ring), ioaddr + PRxCDAR);
+ outl(virt_to_bus(ep->tx_ring), ioaddr + PTxCDAR);
/* Start the chip's Rx process. */
set_rx_mode(dev);
@@ -626,67 +656,160 @@ epic_open(struct device *dev)
dev->start = 1;
/* Enable interrupts by setting the interrupt mask. */
- outl(CntFull | TxUnderrun | TxDone
+ outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
+ | CntFull | TxUnderrun | TxDone
| RxError | RxOverflow | RxFull | RxHeader | RxDone,
ioaddr + INTMASK);
if (epic_debug > 1)
- printk("%s: epic_open() ioaddr %4.4x IRQ %d status %4.4x %s-duplex.\n",
+ printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
+ "%s-duplex.\n",
dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
- full_duplex ? "full" : "half");
+ ep->full_duplex ? "full" : "half");
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
- init_timer(&tp->timer);
- tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
- tp->timer.data = (unsigned long)dev;
- tp->timer.function = &epic_timer; /* timer handler */
- add_timer(&tp->timer);
+ init_timer(&ep->timer);
+ ep->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
+ ep->timer.data = (unsigned long)dev;
+ ep->timer.function = &epic_timer; /* timer handler */
+ add_timer(&ep->timer);
return 0;
}
+/* Reset the chip to recover from a PCI transaction error.
+ This may occur at interrupt time. */
+static void epic_pause(struct device *dev)
+{
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+
+ /* Disable interrupts by clearing the interrupt mask. */
+ outl(0x00000000, ioaddr + INTMASK);
+ /* Stop the chip's Tx and Rx DMA processes. */
+ outw(0x0061, ioaddr + COMMAND);
+
+ /* Update the error counts. */
+ if (inw(ioaddr + COMMAND) != 0xffff) {
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ }
+
+ /* Remove the packets on the Rx queue. */
+ epic_rx(dev);
+}
+
+static void epic_restart(struct device *dev)
+{
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ int i;
+
+ printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
+ dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
+ /* Soft reset the chip. */
+ outl(0x0001, ioaddr + GENCTL);
+
+ udelay(1);
+ /* Duplicate code from epic_open(). */
+ outl(0x0008, ioaddr + TEST1);
+
+#if defined(__powerpc__) /* Big endian */
+ outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#else
+ outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#endif
+ outl(0x12, ioaddr + MIICfg);
+ if (ep->chip_id == 6)
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+
+ for (i = 0; i < 3; i++)
+ outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+
+ outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+ outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR);
+ outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]),
+ ioaddr + PTxCDAR);
+
+ /* Start the chip's Rx process. */
+ set_rx_mode(dev);
+ outl(0x000A, ioaddr + COMMAND);
+
+ /* Enable interrupts by setting the interrupt mask. */
+ outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
+ | CntFull | TxUnderrun | TxDone
+ | RxError | RxOverflow | RxFull | RxHeader | RxDone,
+ ioaddr + INTMASK);
+ printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
+ " interrupt %4.4x.\n",
+ dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL),
+ inl(ioaddr + INTSTAT));
+ return;
+}
+
static void epic_timer(unsigned long data)
{
struct device *dev = (struct device *)data;
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
int next_tick = 0;
+ int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
if (epic_debug > 3) {
- printk("%s: Media selection tick, Tx status %8.8x.\n",
+ printk(KERN_DEBUG "%s: Media selection tick, Tx status %8.8x.\n",
dev->name, inl(ioaddr + TxSTAT));
- printk("%s: Other registers are IntMask %4.4x IntStatus %4.4x RxStatus"
- " %4.4x.\n",
+ printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
+ "IntStatus %4.4x RxStatus %4.4x.\n",
dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
inl(ioaddr + RxSTAT));
}
+ if (! ep->force_fd && mii_reg5 != 0xffff) {
+ int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+ if (ep->full_duplex != duplex) {
+ ep->full_duplex = duplex;
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
+ " partner capability of %4.4x.\n", dev->name,
+ ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
+ outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+ }
+ next_tick = 60*HZ;
+ }
if (next_tick) {
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ ep->timer.expires = RUN_AT(next_tick);
+ add_timer(&ep->timer);
}
}
static void epic_tx_timeout(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
if (epic_debug > 0) {
- printk("%s: Transmit timeout using MII device, Tx status %4.4x.\n",
+ printk(KERN_WARNING "%s: Transmit timeout using MII device, "
+ "Tx status %4.4x.\n",
dev->name, inw(ioaddr + TxSTAT));
if (epic_debug > 1) {
- printk("%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
- dev->name, tp->dirty_tx, tp->cur_tx);
+ printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
+ dev->name, ep->dirty_tx, ep->cur_tx);
}
}
+ if (inw(ioaddr + TxSTAT) & 0x10) { /* Tx FIFO underflow. */
+ ep->stats.tx_fifo_errors++;
+ /* Restart the transmit process. */
+ outl(0x0080, ioaddr + COMMAND);
+ }
+
/* Perhaps stop and restart the chip's Tx processes . */
/* Trigger a transmit demand. */
outl(0x0004, dev->base_addr + COMMAND);
dev->trans_start = jiffies;
- tp->stats.tx_errors++;
+ ep->stats.tx_errors++;
return;
}
@@ -694,66 +817,51 @@ static void epic_tx_timeout(struct device *dev)
static void
epic_init_ring(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
int i;
- tp->tx_full = 0;
- tp->cur_rx = tp->cur_tx = 0;
- tp->dirty_rx = tp->dirty_tx = 0;
+ ep->tx_full = 0;
+ ep->cur_rx = ep->cur_tx = 0;
+ ep->dirty_rx = ep->dirty_tx = 0;
for (i = 0; i < RX_RING_SIZE; i++) {
- tp->rx_ring[i].status = 0x8000; /* Owned by Epic chip */
- tp->rx_ring[i].buflength = PKT_BUF_SZ;
+ ep->rx_ring[i].status = 0x8000; /* Owned by Epic chip */
+ ep->rx_ring[i].buflength = PKT_BUF_SZ;
{
/* Note the receive buffer must be longword aligned.
dev_alloc_skb() provides 16 byte alignment. But do *not*
use skb_reserve() to align the IP header! */
struct sk_buff *skb;
- skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
- tp->rx_skbuff[i] = skb;
+ skb = dev_alloc_skb(PKT_BUF_SZ);
+ ep->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
-#if LINUX_VERSION_CODE > 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- tp->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
-#else
- tp->rx_ring[i].bufaddr = virt_to_bus(skb->data);
-#endif
+ ep->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
}
- tp->rx_ring[i].next = virt_to_bus(&tp->rx_ring[i+1]);
+ ep->rx_ring[i].next = virt_to_bus(&ep->rx_ring[i+1]);
}
/* Mark the last entry as wrapping the ring. */
- tp->rx_ring[i-1].next = virt_to_bus(&tp->rx_ring[0]);
+ ep->rx_ring[i-1].next = virt_to_bus(&ep->rx_ring[0]);
/* The Tx buffer descriptor is filled in as needed, but we
do need to clear the ownership bit. */
for (i = 0; i < TX_RING_SIZE; i++) {
- tp->tx_skbuff[i] = 0;
- tp->tx_ring[i].status = 0x0000;
- tp->tx_ring[i].next = virt_to_bus(&tp->tx_ring[i+1]);
+ ep->tx_skbuff[i] = 0;
+ ep->tx_ring[i].status = 0x0000;
+ ep->tx_ring[i].next = virt_to_bus(&ep->tx_ring[i+1]);
}
- tp->tx_ring[i-1].next = virt_to_bus(&tp->tx_ring[0]);
+ ep->tx_ring[i-1].next = virt_to_bus(&ep->tx_ring[0]);
}
static int
epic_start_xmit(struct sk_buff *skb, struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
int entry;
u32 flag;
-#ifndef final_version
- if (skb == NULL || skb->len <= 0) {
- printk("%s: Obsolete driver layer request made: skbuff==NULL.\n",
- dev->name);
-#if 0
- dev_tint(dev);
-#endif
- return 0;
- }
-#endif
-
/* Block a timer-based transmit from overlapping. This could better be
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
@@ -767,37 +875,40 @@ epic_start_xmit(struct sk_buff *skb, struct device *dev)
with the "ownership" bits last. */
/* Calculate the next Tx descriptor entry. */
- entry = tp->cur_tx % TX_RING_SIZE;
+ entry = ep->cur_tx % TX_RING_SIZE;
- tp->tx_skbuff[entry] = skb;
- tp->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
- tp->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
- tp->tx_ring[entry].buflength = skb->len;
+ ep->tx_skbuff[entry] = skb;
+ ep->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
+ ep->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
+ ep->tx_ring[entry].buflength = skb->len;
- if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+ /* tx_bytes counting -- Nolan Leake */
+ ep->stats.tx_bytes += ep->tx_ring[entry].txlength;
+
+ if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
flag = 0x10; /* No interrupt */
- dev->tbusy = 0;
- } else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+ clear_bit(0, (void*)&dev->tbusy);
+ } else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
flag = 0x14; /* Tx-done intr. */
- dev->tbusy = 0;
- } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+ clear_bit(0, (void*)&dev->tbusy);
+ } else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
flag = 0x10; /* No Tx-done intr. */
- dev->tbusy = 0;
+ clear_bit(0, (void*)&dev->tbusy);
} else {
/* Leave room for two additional entries. */
flag = 0x14; /* Tx-done intr. */
- tp->tx_full = 1;
+ ep->tx_full = 1;
}
- tp->tx_ring[entry].control = flag;
- tp->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */
- tp->cur_tx++;
+ ep->tx_ring[entry].control = flag;
+ ep->tx_ring[entry].status = 0x8000; /* Pass ownership to the chip. */
+ ep->cur_tx++;
/* Trigger an immediate transmit demand. */
outl(0x0004, dev->base_addr + COMMAND);
dev->trans_start = jiffies;
if (epic_debug > 4)
- printk("%s: Queued Tx packet size %d to slot %d, "
+ printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
"flag %2.2x Tx status %8.8x.\n",
dev->name, (int)skb->len, entry, flag,
inl(dev->base_addr + TxSTAT));
@@ -807,27 +918,28 @@ epic_start_xmit(struct sk_buff *skb, struct device *dev)
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
-#ifdef SA_SHIRQ
struct device *dev = (struct device *)dev_instance;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int status, boguscnt = max_interrupt_work;
+
+#if defined(__i386__)
+ /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+ if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+ printk(KERN_ERR "%s: SMP simultaneous entry of an interrupt handler.\n",
+ dev->name);
+ dev->interrupt = 0; /* Avoid halting machine. */
+ return;
+ }
#else
- struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
- struct epic_private *lp;
- int status, ioaddr, boguscnt = max_interrupt_work;
-
- if (dev == NULL) {
- printk ("epic_interrupt(): irq %d for unknown device.\n", irq);
+ if (dev->interrupt) {
+ printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
return;
}
-
- ioaddr = dev->base_addr;
- lp = (struct epic_private *)dev->priv;
- if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
dev->interrupt = 1;
+#endif
do {
status = inl(ioaddr + INTSTAT);
@@ -838,18 +950,18 @@ static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs
printk("%s: interrupt interrupt=%#8.8x new intstat=%#8.8x.\n",
dev->name, status, inl(ioaddr + INTSTAT));
- if ((status & (RxDone | TxEmpty | TxDone)) == 0)
+ if ((status & IntrSummary) == 0)
break;
- if (status & RxDone) /* Rx interrupt */
+ if (status & (RxDone | RxStarted | RxEarlyWarn))
epic_rx(dev);
if (status & (TxEmpty | TxDone)) {
int dirty_tx;
- for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+ for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) {
int entry = dirty_tx % TX_RING_SIZE;
- int txstatus = lp->tx_ring[entry].status;
+ int txstatus = ep->tx_ring[entry].status;
if (txstatus < 0)
break; /* It still hasn't been Txed */
@@ -861,66 +973,77 @@ static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs
printk("%s: Transmit error, Tx status %8.8x.\n",
dev->name, txstatus);
#endif
- lp->stats.tx_errors++;
- if (txstatus & 0x1050) lp->stats.tx_aborted_errors++;
- if (txstatus & 0x0008) lp->stats.tx_carrier_errors++;
- if (txstatus & 0x0040) lp->stats.tx_window_errors++;
- if (txstatus & 0x0010) lp->stats.tx_fifo_errors++;
+ ep->stats.tx_errors++;
+ if (txstatus & 0x1050) ep->stats.tx_aborted_errors++;
+ if (txstatus & 0x0008) ep->stats.tx_carrier_errors++;
+ if (txstatus & 0x0040) ep->stats.tx_window_errors++;
+ if (txstatus & 0x0010) ep->stats.tx_fifo_errors++;
#ifdef ETHER_STATS
- if (txstatus & 0x1000) lp->stats.collisions16++;
+ if (txstatus & 0x1000) ep->stats.collisions16++;
#endif
} else {
#ifdef ETHER_STATS
- if ((txstatus & 0x0002) != 0) lp->stats.tx_deferred++;
+ if ((txstatus & 0x0002) != 0) ep->stats.tx_deferred++;
#endif
- lp->stats.collisions += (txstatus >> 8) & 15;
- lp->stats.tx_packets++;
+ ep->stats.collisions += (txstatus >> 8) & 15;
+ ep->stats.tx_packets++;
}
/* Free the original skb. */
- dev_kfree_skb(lp->tx_skbuff[entry]);
- lp->tx_skbuff[entry] = 0;
+ DEV_FREE_SKB(ep->tx_skbuff[entry]);
+ ep->tx_skbuff[entry] = 0;
}
#ifndef final_version
- if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+ if (ep->cur_tx - dirty_tx > TX_RING_SIZE) {
printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
- dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+ dev->name, dirty_tx, ep->cur_tx, ep->tx_full);
dirty_tx += TX_RING_SIZE;
}
#endif
- if (lp->tx_full && dev->tbusy
- && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ if (ep->tx_full && dev->tbusy
+ && dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
/* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
- dev->tbusy = 0;
+ ep->tx_full = 0;
+ clear_bit(0, (void*)&dev->tbusy);
mark_bh(NET_BH);
}
- lp->dirty_tx = dirty_tx;
+ ep->dirty_tx = dirty_tx;
}
/* Check uncommon events all at once. */
- if (status & (CntFull | TxUnderrun | RxOverflow)) {
+ if (status & (CntFull | TxUnderrun | RxOverflow |
+ PCIBusErr170 | PCIBusErr175)) {
+ if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
+ break;
/* Always update the error counts to avoid overhead later. */
- lp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- lp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- lp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
if (status & TxUnderrun) { /* Tx FIFO underflow. */
- lp->stats.tx_fifo_errors++;
- /* Restart the transmit process. */
- outl(0x0080, ioaddr + COMMAND);
+ ep->stats.tx_fifo_errors++;
+ outl(1536, ioaddr + TxThresh);
+ /* Restart the transmit process. */
+ outl(0x0080, ioaddr + COMMAND);
}
if (status & RxOverflow) { /* Missed a Rx frame. */
- lp->stats.rx_errors++;
+ ep->stats.rx_errors++;
+ }
+ if (status & PCIBusErr170) {
+ printk(KERN_ERR "%s: PCI Bus Error! EPIC status %4.4x.\n",
+ dev->name, status);
+ epic_pause(dev);
+ epic_restart(dev);
}
/* Clear all error sources. */
outl(status & 0x7f18, ioaddr + INTSTAT);
}
if (--boguscnt < 0) {
- printk("%s: Too much work at interrupt, IntrStatus=0x%8.8x.\n",
+ printk(KERN_ERR "%s: Too much work at interrupt, "
+ "IntrStatus=0x%8.8x.\n",
dev->name, status);
/* Clear all interrupt sources. */
outl(0x0001ffff, ioaddr + INTSTAT);
@@ -929,133 +1052,103 @@ static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs
} while (1);
if (epic_debug > 3)
- printk("%s: exiting interrupt, intr_status=%#4.4x.\n",
+ printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
dev->name, inl(ioaddr + INTSTAT));
- /* Code that should never be run! Perhaps remove after testing.. */
- {
- static int stopit = 10;
- if (dev->start == 0 && --stopit < 0) {
- printk("%s: Emergency stop, looping startup interrupt.\n",
- dev->name);
- FREE_IRQ(irq, dev);
- }
- }
-
+#if defined(__i386__)
+ clear_bit(0, (void*)&dev->interrupt);
+#else
dev->interrupt = 0;
+#endif
return;
}
-static int
-epic_rx(struct device *dev)
+static int epic_rx(struct device *dev)
{
- struct epic_private *lp = (struct epic_private *)dev->priv;
- int entry = lp->cur_rx % RX_RING_SIZE;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ int entry = ep->cur_rx % RX_RING_SIZE;
+ int work_done = 0;
if (epic_debug > 4)
- printk(" In epic_rx(), entry %d %8.8x.\n", entry,
- lp->rx_ring[entry].status);
+ printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
+ ep->rx_ring[entry].status);
/* If we own the next entry, it's a new packet. Send it up. */
- while (lp->rx_ring[entry].status >= 0) {
- int status = lp->rx_ring[entry].status;
+ while (ep->rx_ring[entry].status >= 0 && ep->rx_skbuff[entry]) {
+ int status = ep->rx_ring[entry].status;
if (epic_debug > 4)
- printk(" epic_rx() status was %8.8x.\n", status);
- if (status & 0x2000) {
- printk("%s: Oversized Ethernet frame spanned multiple buffers,"
- " status %4.4x!\n", dev->name, status);
- lp->stats.rx_length_errors++;
- } else if (status & 0x0006) {
- /* Rx Frame errors are counted in hardware. */
- lp->stats.rx_errors++;
+ printk(KERN_DEBUG " epic_rx() status was %8.8x.\n", status);
+ if (status & 0x2006) {
+ if (status & 0x2000) {
+ printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
+ "multiple buffers, status %4.4x!\n", dev->name, status);
+ ep->stats.rx_length_errors++;
+ } else if (status & 0x0006)
+ /* Rx Frame errors are counted in hardware. */
+ ep->stats.rx_errors++;
} else {
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
- short pkt_len = lp->rx_ring[entry].rxlength - 4;
+ short pkt_len = ep->rx_ring[entry].rxlength - 4;
struct sk_buff *skb;
- int rx_in_place = 0;
-
- /* Check if the packet is long enough to just accept without
- copying to a properly sized skbuff. */
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
- char *temp;
-
- /* Pass up the skb already on the Rx ring. */
- skb = lp->rx_skbuff[entry];
- temp = skb_put(skb, pkt_len);
- if (bus_to_virt(lp->rx_ring[entry].bufaddr) != temp)
- printk("%s: Warning -- the skbuff addresses do not match"
- " in epic_rx: %p vs. %p / %p.\n", dev->name,
- bus_to_virt(lp->rx_ring[entry].bufaddr),
- skb->head, temp);
- /* Get a fresh skbuff to replace the filled one. */
- newskb = DEV_ALLOC_SKB(PKT_BUF_SZ);
- if (newskb) {
- rx_in_place = 1;
- lp->rx_skbuff[entry] = newskb;
- newskb->dev = dev;
-#if LINUX_VERSION_CODE > 0x10300
- /* Align IP on 16 byte boundaries */
- skb_reserve(newskb, 2);
- lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->tail);
+
+ /* Check if the packet is long enough to accept without copying
+ to a minimally-sized skbuff. */
+ if (pkt_len < rx_copybreak
+ && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+#if 1 /* USE_IP_COPYSUM */
+ eth_copy_and_sum(skb, bus_to_virt(ep->rx_ring[entry].bufaddr),
+ pkt_len, 0);
+ skb_put(skb, pkt_len);
#else
- lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->data);
-#endif
- } else /* No memory, drop the packet. */
- skb = 0;
- } else
- skb = DEV_ALLOC_SKB(pkt_len + 2);
- if (skb == NULL) {
- int i;
- printk("%s: Memory squeeze, deferring packet.\n", dev->name);
- /* Check that at least two ring entries are free.
- If not, free one and mark stats->rx_dropped++. */
- for (i = 0; i < RX_RING_SIZE; i++)
- if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0)
- break;
-
- if (i > RX_RING_SIZE -2) {
- lp->stats.rx_dropped++;
- lp->rx_ring[entry].status = 0x8000;
- lp->cur_rx++;
- }
- break;
- }
- skb->dev = dev;
- if (! rx_in_place) {
- skb_reserve(skb, 2); /* 16 byte align the data fields */
memcpy(skb_put(skb, pkt_len),
- bus_to_virt(lp->rx_ring[entry].bufaddr), pkt_len);
+ bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len);
+#endif
+ } else {
+ skb_put(skb = ep->rx_skbuff[entry], pkt_len);
+ ep->rx_skbuff[entry] = NULL;
}
-#if LINUX_VERSION_CODE > 0x10300
skb->protocol = eth_type_trans(skb, dev);
-#else
- skb->len = pkt_len;
-#endif
netif_rx(skb);
- lp->stats.rx_packets++;
+ ep->stats.rx_packets++;
+ /* rx_bytes counting -- Nolan Leake */
+ ep->stats.rx_bytes += pkt_len;
}
-
- lp->rx_ring[entry].status = 0x8000;
- entry = (++lp->cur_rx) % RX_RING_SIZE;
+ work_done++;
+ entry = (++ep->cur_rx) % RX_RING_SIZE;
}
- return 0;
+ /* Refill the Rx ring buffers. */
+ for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) {
+ entry = ep->dirty_rx % RX_RING_SIZE;
+ if (ep->rx_skbuff[entry] == NULL) {
+ struct sk_buff *skb;
+ skb = ep->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+ if (skb == NULL)
+ break;
+ skb->dev = dev; /* Mark as being used by this device. */
+ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
+ ep->rx_ring[entry].bufaddr = virt_to_bus(skb->tail);
+ work_done++;
+ }
+ ep->rx_ring[entry].status = 0x8000;
+ }
+ return work_done;
}
-static int
-epic_close(struct device *dev)
+static int epic_close(struct device *dev)
{
- int ioaddr = dev->base_addr;
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
int i;
dev->start = 0;
dev->tbusy = 1;
if (epic_debug > 1)
- printk("%s: Shutting down ethercard, status was %2.2x.\n",
+ printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
dev->name, inl(ioaddr + INTSTAT));
/* Disable interrupts by clearing the interrupt mask. */
@@ -1064,67 +1157,61 @@ epic_close(struct device *dev)
outw(0x0061, ioaddr + COMMAND);
/* Update the error counts. */
- tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
- del_timer(&tp->timer);
+ del_timer(&ep->timer);
-#ifdef SA_SHIRQ
free_irq(dev->irq, dev);
-#else
- free_irq(dev->irq);
- irq2dev_map[dev->irq] = 0;
-#endif
/* Free all the skbuffs in the Rx queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = tp->rx_skbuff[i];
- tp->rx_skbuff[i] = 0;
- tp->rx_ring[i].status = 0; /* Not owned by Epic chip. */
- tp->rx_ring[i].buflength = 0;
- tp->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
+ struct sk_buff *skb = ep->rx_skbuff[i];
+ ep->rx_skbuff[i] = 0;
+ ep->rx_ring[i].status = 0; /* Not owned by Epic chip. */
+ ep->rx_ring[i].buflength = 0;
+ ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
if (skb) {
#if LINUX_VERSION_CODE < 0x20100
skb->free = 1;
#endif
- dev_kfree_skb(skb);
+ DEV_FREE_SKB(skb);
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
- if (tp->tx_skbuff[i])
- dev_kfree_skb(tp->tx_skbuff[i]);
- tp->tx_skbuff[i] = 0;
+ if (ep->tx_skbuff[i])
+ DEV_FREE_SKB(ep->tx_skbuff[i]);
+ ep->tx_skbuff[i] = 0;
}
/* Green! Leave the chip in low-power mode. */
outl(0x0008, ioaddr + GENCTL);
-
+
MOD_DEC_USE_COUNT;
return 0;
}
-static struct enet_statistics *
-epic_get_stats(struct device *dev)
+static struct net_device_stats *epic_get_stats(struct device *dev)
{
- struct epic_private *tp = (struct epic_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
if (dev->start) {
/* Update the error counts. */
- tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
- tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
- tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+ ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+ ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+ ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
}
- return &tp->stats;
+ return &ep->stats;
}
/* Set or clear the multicast filter for this adaptor.
Note that we only use exclusion around actually queueing the
- new frame, not around filling tp->setup_frame. This is non-deterministic
+ new frame, not around filling ep->setup_frame. This is non-deterministic
when re-entered but still correct. */
/* The little-endian AUTODIN II ethernet CRC calculation.
@@ -1149,21 +1236,17 @@ static inline unsigned ether_crc_le(int length, unsigned char *data)
}
-#ifdef NEW_MULTICAST
static void set_rx_mode(struct device *dev)
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
{
- int ioaddr = dev->base_addr;
- struct epic_private *tp = (struct epic_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ struct epic_private *ep = (struct epic_private *)dev->priv;
unsigned char mc_filter[8]; /* Multicast hash filter */
int i;
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
outl(0x002C, ioaddr + RxCtrl);
/* Unconditionally log net taps. */
- printk("%s: Promiscuous mode enabled.\n", dev->name);
+ printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
memset(mc_filter, 0xff, sizeof(mc_filter));
} else if ((dev->mc_count > 0) || (dev->flags & IFF_ALLMULTI)) {
/* There is apparently a chip bug, so the multicast filter
@@ -1184,45 +1267,176 @@ static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
mc_filter);
}
/* ToDo: perhaps we need to stop the Tx and Rx process here? */
- if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
+ if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) {
for (i = 0; i < 4; i++)
outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
- memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+ memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));
}
return;
}
+
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+ long ioaddr = dev->base_addr;
+ u16 *data = (u16 *)&rq->ifr_data;
+
+ switch(cmd) {
+ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
+ data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f;
+ /* Fall Through */
+ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
+ if (! dev->start) {
+ outl(0x0200, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ }
+ data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+ if (! dev->start) {
+#ifdef notdef
+ outl(0x0008, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+#endif
+ }
+ return 0;
+ case SIOCDEVPRIVATE+2: /* Write the specified MII register */
+ if (!suser())
+ return -EPERM;
+ if (! dev->start) {
+ outl(0x0200, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+ }
+ mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+ if (! dev->start) {
+#ifdef notdef
+ outl(0x0008, ioaddr + GENCTL);
+ outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+#endif
+ }
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
-#ifdef MODULE
+#ifdef CARDBUS
-/* An additional parameter that may be passed in... */
-static int debug = -1;
+#include <pcmcia/driver_ops.h>
-int
-init_module(void)
+static dev_node_t *epic_attach(dev_locator_t *loc)
{
- int cards_found;
+ struct device *dev;
+ u16 dev_id;
+ u32 io;
+ u8 bus, devfn, irq;
+
+ if (loc->bus != LOC_PCI) return NULL;
+ bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+ printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
+ pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
+ pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+ pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ io &= ~3;
+ if (io == 0 || irq == 0) {
+ printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
+ "assigned an %s.\n" KERN_ERR " It will not be activated.\n",
+ io == 0 ? "I/O address" : "IRQ");
+ return NULL;
+ }
+ dev = epic_probe1(bus, devfn, NULL, io, irq, 2, -1);
+ if (dev) {
+ dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+ strcpy(node->dev_name, dev->name);
+ node->major = node->minor = 0;
+ node->next = NULL;
+ MOD_INC_USE_COUNT;
+ return node;
+ }
+ return NULL;
+}
- if (debug >= 0)
- epic_debug = debug;
+static void epic_suspend(dev_node_t *node)
+{
+ struct device **devp, **next;
+ printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
+ for (devp = &root_epic_dev; *devp; devp = next) {
+ next = &((struct epic_private *)(*devp)->priv)->next_module;
+ if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ }
+ if (*devp) {
+ long ioaddr = (*devp)->base_addr;
+ epic_pause(*devp);
+ /* Put the chip into low-power mode. */
+ outl(0x0008, ioaddr + GENCTL);
+ }
+}
+static void epic_resume(dev_node_t *node)
+{
+ struct device **devp, **next;
+ printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
+ for (devp = &root_epic_dev; *devp; devp = next) {
+ next = &((struct epic_private *)(*devp)->priv)->next_module;
+ if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ }
+ if (*devp) {
+ epic_restart(*devp);
+ }
+}
+static void epic_detach(dev_node_t *node)
+{
+ struct device **devp, **next;
+ printk(KERN_INFO "epic_detach(%s)\n", node->dev_name);
+ for (devp = &root_epic_dev; *devp; devp = next) {
+ next = &((struct epic_private *)(*devp)->priv)->next_module;
+ if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ }
+ if (*devp) {
+ unregister_netdev(*devp);
+ kfree(*devp);
+ *devp = *next;
+ kfree(node);
+ MOD_DEC_USE_COUNT;
+ }
+}
- root_epic_dev = NULL;
- cards_found = epic100_probe(0);
+struct driver_operations epic_ops = {
+ "epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach
+};
- return cards_found ? 0 : -ENODEV;
+#endif /* Cardbus support */
+
+
+#ifdef MODULE
+
+int init_module(void)
+{
+ if (epic_debug)
+ printk(KERN_INFO "%s", version);
+
+#ifdef CARDBUS
+ register_driver(&epic_ops);
+ return 0;
+#else
+ return epic100_probe(0);
+#endif
}
-void
-cleanup_module(void)
+void cleanup_module(void)
{
struct device *next_dev;
+#ifdef CARDBUS
+ unregister_driver(&epic_ops);
+#endif
+
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_epic_dev) {
- next_dev = ((struct epic_private *)root_epic_dev->priv)->next_module;
+ struct epic_private *ep = (struct epic_private *)root_epic_dev->priv;
+ next_dev = ep->next_module;
unregister_netdev(root_epic_dev);
release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
kfree(root_epic_dev);
root_epic_dev = next_dev;
+ kfree(ep);
}
}
@@ -1230,7 +1444,8 @@ cleanup_module(void)
/*
* Local variables:
- * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index 6aeb146db..f57e76cda 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -439,7 +439,6 @@ cleanup_module(void)
void *priv = dev->priv;
free_irq(dev->irq, dev);
release_region(dev->base_addr, ES_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index 59921bfc2..391f6194a 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -799,12 +799,12 @@ static int eth16i_receive_probe_packet(int ioaddr)
if( (jiffies - starttime) > TX_TIMEOUT) {
if(eth16i_debug > 1)
- printk(KERN_DEBUG "Timeout occured waiting transmit packet received\n");
+ printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
starttime = jiffies;
while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
if( (jiffies - starttime) > TX_TIMEOUT) {
if(eth16i_debug > 1)
- printk(KERN_DEBUG "Timeout occured waiting receive packet\n");
+ printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
return -1;
}
}
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
index 3350d0d5c..749e1f123 100644
--- a/drivers/net/fmv18x.c
+++ b/drivers/net/fmv18x.c
@@ -32,7 +32,7 @@
*/
static const char *version =
- "fmv18x.c:v1.3.71e 03/04/96 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
+ "fmv18x.c:v2.2.0 09/24/98 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
#include <linux/module.h>
@@ -74,6 +74,8 @@ struct net_local {
struct net_device_stats stats;
long open_time; /* Useless example local info. */
uint tx_started:1; /* Number of packet on the Tx queue. */
+ uint tx_queue_ready:1; /* Tx queue is ready to be sent. */
+ uint rx_started:1; /* Packets are Rxing. */
uchar tx_queue; /* Number of packet on the Tx queue. */
ushort tx_queue_len; /* Current length of the Tx queue. */
};
@@ -92,7 +94,7 @@ struct net_local {
/* Run-time register bank 2 definitions. */
#define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */
#define TX_START 10
-#define COL16CNTL 11
+#define COL16CNTL 11 /* Controll Reg for 16 collisions */
#define MODE13 13
/* Fujitsu FMV-18x Card Configuration */
#define FJ_STATUS0 0x10
@@ -164,6 +166,7 @@ fmv18x_probe(struct device *dev))
__initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
{
char irqmap[4] = {3, 7, 10, 15};
+ char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
unsigned int i, irq;
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
@@ -171,13 +174,26 @@ __initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
*/
/* Check I/O address configuration and Fujitsu vendor code */
- if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr
- || inb(ioaddr+FJ_MACADDR ) != 0x00
+ if (inb(ioaddr+FJ_MACADDR ) != 0x00
|| inb(ioaddr+FJ_MACADDR+1) != 0x00
|| inb(ioaddr+FJ_MACADDR+2) != 0x0e)
return -ENODEV;
- irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
+ /* Check PnP mode for FMV-183/184/183A/184A. */
+ /* This PnP routine is very poor. IO and IRQ should be known. */
+ if (inb(ioaddr + FJ_STATUS1) & 0x20) {
+ irq = dev->irq;
+ for (i = 0; i < 8; i++) {
+ if (irq == irqmap_pnp[i])
+ break;
+ }
+ if (i == 8)
+ return -ENODEV;
+ } else {
+ if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
+ return -ENODEV;
+ irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
+ }
/* Snarf the interrupt vector now. */
if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) {
@@ -247,6 +263,7 @@ __initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
/* Switch to bank 2 and lock our I/O address. */
outb(0x08, ioaddr + CONFIG_1);
outb(dev->if_port, ioaddr + MODE13);
+ outb(0x00, ioaddr + COL16CNTL);
if (net_debug)
printk(version);
@@ -283,6 +300,8 @@ static int net_open(struct device *dev)
outb(0xe8, ioaddr + CONFIG_1);
lp->tx_started = 0;
+ lp->tx_queue_ready = 1;
+ lp->rx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
@@ -364,14 +383,20 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
printk("%s: Transmitting a packet of length %lu.\n", dev->name,
(unsigned long)skb->len);
- /* Disable both interrupts. */
- outw(0x0000, ioaddr + TX_INTR);
-
- outw(length, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
+ /* We may not start transmitting unless we finish transferring
+ a packet into the Tx queue. During executing the following
+ codes we possibly catch a Tx interrupt. Thus we flag off
+ tx_queue_ready, so that we prevent the interrupt routine
+ (net_interrupt) to start transmitting. */
+ lp->tx_queue_ready = 0;
+ {
+ outw(length, ioaddr + DATAPORT);
+ outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+
+ lp->tx_queue++;
+ lp->tx_queue_len += length + 2;
+ }
+ lp->tx_queue_ready = 1;
if (lp->tx_started == 0) {
/* If the Tx is idle, always trigger a transmit. */
@@ -384,9 +409,6 @@ net_send_packet(struct sk_buff *skb, struct device *dev)
} else if (lp->tx_queue_len < 4096 - 1502)
/* Yes, there is room for one more packet. */
dev->tbusy = 0;
-
- /* Re-enable interrupts */
- outw(0x8182, ioaddr + TX_INTR);
}
dev_kfree_skb (skb);
@@ -410,23 +432,37 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ioaddr = dev->base_addr;
lp = (struct net_local *)dev->priv;
-
- /* Avoid multiple interrupts. */
- outw(0x0000, ioaddr + TX_INTR);
-
- status = inw(ioaddr + TX_STATUS);
+ status = inw(ioaddr + TX_STATUS);
outw(status, ioaddr + TX_STATUS);
if (net_debug > 4)
printk("%s: Interrupt with status %04x.\n", dev->name, status);
- if (status & 0xff00
- || (inb(ioaddr + RX_MODE) & 0x40) == 0) { /* Got a packet(s). */
+ if (lp->rx_started == 0 &&
+ (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
+ /* Got a packet(s).
+ We cannot execute net_rx more than once at the same time for
+ the same device. During executing net_rx, we possibly catch a
+ Tx interrupt. Thus we flag on rx_started, so that we prevent
+ the interrupt routine (net_interrupt) to dive into net_rx
+ again. */
+ lp->rx_started = 1;
+ outb(0x00, ioaddr + RX_INTR); /* Disable RX intr. */
net_rx(dev);
+ outb(0x81, ioaddr + RX_INTR); /* Enable RX intr. */
+ lp->rx_started = 0;
}
if (status & 0x00ff) {
- if (status & 0x80) {
+ if (status & 0x02) {
+ /* More than 16 collisions occurred */
+ if (net_debug > 4)
+ printk("%s: 16 Collision occur during Txing.\n", dev->name);
+ /* Cancel sending a packet. */
+ outb(0x03, ioaddr + COL16CNTL);
+ lp->stats.collisions++;
+ }
+ if (status & 0x82) {
lp->stats.tx_packets++;
- if (lp->tx_queue) {
+ if (lp->tx_queue && lp->tx_queue_ready) {
outb(0x80 | lp->tx_queue, ioaddr + TX_START);
lp->tx_queue = 0;
lp->tx_queue_len = 0;
@@ -439,16 +475,9 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
mark_bh(NET_BH); /* Inform upper layers. */
}
}
- if (status & 0x02 ) {
- if (net_debug > 4)
- printk("%s: 16 Collision occur during Txing.\n", dev->name);
- /* Retry to send the packet */
- outb(0x02, ioaddr + COL16CNTL);
- }
}
dev->interrupt = 0;
- outw(0x8182, ioaddr + TX_INTR);
return;
}
@@ -458,7 +487,7 @@ net_rx(struct device *dev)
{
struct net_local *lp = (struct net_local *)dev->priv;
int ioaddr = dev->base_addr;
- int boguscount = 10; /* 5 -> 10: by agy 19940922 */
+ int boguscount = 5;
while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
/* Clear PKT_RDY bit: by agy 19940922 */
@@ -619,6 +648,7 @@ static int irq = 0;
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
+MODULE_PARM(net_debug, "i");
int init_module(void)
{
diff --git a/drivers/net/hamradio/Config.in b/drivers/net/hamradio/Config.in
index 2aaa087a1..023a4b1b6 100644
--- a/drivers/net/hamradio/Config.in
+++ b/drivers/net/hamradio/Config.in
@@ -13,8 +13,8 @@ fi
tristate 'BAYCOM ser12 fullduplex driver for AX.25' CONFIG_BAYCOM_SER_FDX
tristate 'BAYCOM ser12 halfduplex driver for AX.25' CONFIG_BAYCOM_SER_HDX
-tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR
-tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP
+dep_tristate 'BAYCOM picpar and par96 driver for AX.25' CONFIG_BAYCOM_PAR $CONFIG_PARPORT
+dep_tristate 'BAYCOM epp driver for AX.25' CONFIG_BAYCOM_EPP $CONFIG_PARPORT
tristate 'Soundcard modem driver' CONFIG_SOUNDMODEM
if [ "$CONFIG_SOUNDMODEM" != "n" ]; then
diff --git a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
index cf6d0dfeb..6129b4b44 100644
--- a/drivers/net/hamradio/baycom_ser_fdx.c
+++ b/drivers/net/hamradio/baycom_ser_fdx.c
@@ -83,6 +83,7 @@
#include <linux/netdevice.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
+#include <linux/version.h>
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
index f472c8b9e..088f9318e 100644
--- a/drivers/net/hamradio/baycom_ser_hdx.c
+++ b/drivers/net/hamradio/baycom_ser_hdx.c
@@ -72,6 +72,7 @@
#include <linux/netdevice.h>
#include <linux/hdlcdrv.h>
#include <linux/baycom.h>
+#include <linux/version.h>
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index 258c5c58c..b2358447d 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -41,6 +41,7 @@
/*****************************************************************************/
#include <linux/config.h>
+#include <linux/version.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
@@ -58,10 +59,8 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/hdlcdrv.h>
-#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
/* prototypes for ax25_encapsulate and ax25_rebuild_header */
#include <net/ax25.h>
-#endif /* CONFIG_AX25 || CONFIG_AX25_MODULE */
/* make genksyms happy */
#include <linux/ip.h>
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index 736d6b26b..48ef86a9b 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1,4 +1,4 @@
-#define RCS_ID "$Id: scc.c,v 1.73 1998/01/29 17:38:51 jreuter Exp jreuter $"
+#define RCS_ID "$Id: scc.c,v 1.75 1998/11/04 15:15:01 jreuter Exp jreuter $"
#define VERSION "3.0"
#define BANNER "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
@@ -60,22 +60,22 @@
Incomplete history of z8530drv:
-------------------------------
- 940913 - started to write the driver, rescued most of my own
- code (and Hans Alblas' memory buffer pool concept) from
- an earlier project "sccdrv" which was initiated by
- Guido ten Dolle. Not much of the old driver survived,
- though. The first version I put my hands on was sccdrv1.3
- from August 1993. The memory buffer pool concept
- appeared in an unauthorized sccdrv version (1.5) from
- August 1994.
+ 1994-09-13 started to write the driver, rescued most of my own
+ code (and Hans Alblas' memory buffer pool concept) from
+ an earlier project "sccdrv" which was initiated by
+ Guido ten Dolle. Not much of the old driver survived,
+ though. The first version I put my hands on was sccdrv1.3
+ from August 1993. The memory buffer pool concept
+ appeared in an unauthorized sccdrv version (1.5) from
+ August 1994.
- 950131 - changed copyright notice to GPL without limitations.
+ 1995-01-31 changed copyright notice to GPL without limitations.
.
. <SNIP>
.
- 961005 - New semester, new driver...
+ 1996-10-05 New semester, new driver...
* KISS TNC emulator removed (TTY driver)
* Source moved to drivers/net/
@@ -88,12 +88,22 @@
The move to version number 3.0 reflects theses changes.
You can use 'kissbridge' if you need a KISS TNC emulator.
- 961213 - Fixed for Linux networking changes. (G4KLX)
- 970108 - Fixed the remaining problems.
- 970402 - Hopefully fixed the problems with the new *_timer()
- routines, added calibration code.
- 971012 - Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO
- 980129 - Small fix to avoid lock-up on initialization
+ 1996-12-13 Fixed for Linux networking changes. (G4KLX)
+ 1997-01-08 Fixed the remaining problems.
+ 1997-04-02 Hopefully fixed the problems with the new *_timer()
+ routines, added calibration code.
+ 1997-10-12 Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO
+ 1998-01-29 Small fix to avoid lock-up on initialization
+ 1998-09-29 Fixed the "grouping" bugs, tx_inhibit works again,
+ using dev->tx_queue_len now instead of MAXQUEUE now.
+ 1998-10-21 Postponed the spinlock changes, would need a lot of
+ testing I currently don't have the time to. Softdcd doesn't
+ work.
+ 1998-11-04 Softdcd does not work correctly in DPLL mode, in fact it
+ never did. The DPLL locks on noise, the SYNC unit sees
+ flags that aren't... Restarting the DPLL does not help
+ either, it resynchronizes too slow and the first received
+ frame gets lost.
Thanks to all who contributed to this driver with ideas and bug
reports!
@@ -119,22 +129,22 @@
Joerg Reuter ampr-net: dl1bke@db0pra.ampr.org
AX-25 : DL1BKE @ DB0ACH.#NRW.DEU.EU
Internet: jreuter@poboxes.com
- www : http://www.rat.de/jr
+ www : http://poboxes.com/jreuter/
*/
/* ----------------------------------------------------------------------- */
#undef SCC_LDELAY 1 /* slow it even a bit more down */
-#undef DONT_CHECK /* don't look if the SCCs you specified are available */
+#undef SCC_DONT_CHECK /* don't look if the SCCs you specified are available */
-#define MAXSCC 4 /* number of max. supported chips */
-#define BUFSIZE 384 /* must not exceed 4096 */
-#define MAXQUEUE 8 /* number of buffers we queue ourself */
-#undef DISABLE_ALL_INTS /* use cli()/sti() in ISR instead of */
+#define SCC_MAXCHIPS 4 /* number of max. supported chips */
+#define SCC_BUFSIZE 384 /* must not exceed 4096 */
+#undef SCC_DISABLE_ALL_INTS /* use cli()/sti() in ISR instead of */
/* enable_irq()/disable_irq() */
#undef SCC_DEBUG
-#define DEFAULT_CLOCK 4915200 /* default pclock if nothing is specified */
+#define SCC_DEFAULT_CLOCK 4915200
+ /* default pclock if nothing is specified */
/* ----------------------------------------------------------------------- */
@@ -214,13 +224,13 @@ static unsigned char *SCC_DriverName = "scc";
static struct irqflags { unsigned char used : 1; } Ivec[16];
-static struct scc_channel SCC_Info[2 * MAXSCC]; /* information per channel */
+static struct scc_channel SCC_Info[2 * SCC_MAXCHIPS]; /* information per channel */
static struct scc_ctrl {
io_port chan_A;
io_port chan_B;
int irq;
-} SCC_ctrl[MAXSCC+1];
+} SCC_ctrl[SCC_MAXCHIPS+1];
static unsigned char Driver_Initialized = 0;
static int Nchips = 0;
@@ -236,7 +246,7 @@ MODULE_SUPPORTED_DEVICE("scc");
/* These provide interrupt save 2-step access to the Z8530 registers */
-extern __inline__ unsigned char InReg(io_port port, unsigned char reg)
+static inline unsigned char InReg(io_port port, unsigned char reg)
{
unsigned long flags;
unsigned char r;
@@ -256,7 +266,7 @@ extern __inline__ unsigned char InReg(io_port port, unsigned char reg)
return r;
}
-extern __inline__ void OutReg(io_port port, unsigned char reg, unsigned char val)
+static inline void OutReg(io_port port, unsigned char reg, unsigned char val)
{
unsigned long flags;
@@ -272,31 +282,31 @@ extern __inline__ void OutReg(io_port port, unsigned char reg, unsigned char val
restore_flags(flags);
}
-extern __inline__ void wr(struct scc_channel *scc, unsigned char reg,
+static inline void wr(struct scc_channel *scc, unsigned char reg,
unsigned char val)
{
OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
}
-extern __inline__ void or(struct scc_channel *scc, unsigned char reg, unsigned char val)
+static inline void or(struct scc_channel *scc, unsigned char reg, unsigned char val)
{
OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
}
-extern __inline__ void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
+static inline void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
{
OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
}
-#ifdef DISABLE_ALL_INTS
-extern __inline__ void scc_cli(int irq)
+#ifdef SCC_DISABLE_ALL_INTS
+static inline void scc_cli(int irq)
{ cli(); }
-extern __inline__ void scc_sti(int irq)
+static inline void scc_sti(int irq)
{ sti(); }
#else
-static __inline__ void scc_cli(int irq)
+static inline void scc_cli(int irq)
{ disable_irq(irq); }
-static __inline__ void scc_sti(int irq)
+static inline void scc_sti(int irq)
{ enable_irq(irq); }
#endif
@@ -305,17 +315,17 @@ static __inline__ void scc_sti(int irq)
/* ******************************************************************** */
-extern __inline__ void scc_lock_dev(struct scc_channel *scc)
+static inline void scc_lock_dev(struct scc_channel *scc)
{
scc->dev->tbusy = 1;
}
-extern __inline__ void scc_unlock_dev(struct scc_channel *scc)
+static inline void scc_unlock_dev(struct scc_channel *scc)
{
scc->dev->tbusy = 0;
}
-extern __inline__ void scc_discard_buffers(struct scc_channel *scc)
+static inline void scc_discard_buffers(struct scc_channel *scc)
{
unsigned long flags;
@@ -343,7 +353,7 @@ extern __inline__ void scc_discard_buffers(struct scc_channel *scc)
/* ----> subroutines for the interrupt handlers <---- */
-extern __inline__ void scc_notify(struct scc_channel *scc, int event)
+static inline void scc_notify(struct scc_channel *scc, int event)
{
struct sk_buff *skb;
char *bp;
@@ -362,7 +372,7 @@ extern __inline__ void scc_notify(struct scc_channel *scc, int event)
scc->stat.nospace++;
}
-extern __inline__ void flush_rx_FIFO(struct scc_channel *scc)
+static inline void flush_rx_FIFO(struct scc_channel *scc)
{
int k;
@@ -377,12 +387,18 @@ extern __inline__ void flush_rx_FIFO(struct scc_channel *scc)
}
}
+static void start_hunt(struct scc_channel *scc)
+{
+ if ((scc->modem.clocksrc != CLK_EXTERNAL))
+ OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
+ or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
+}
/* ----> four different interrupt handlers for Tx, Rx, changing of */
/* DCD/CTS and Rx/Tx errors */
/* Transmitter interrupt handler */
-extern __inline__ void scc_txint(struct scc_channel *scc)
+static inline void scc_txint(struct scc_channel *scc)
{
struct sk_buff *skb;
@@ -446,7 +462,7 @@ extern __inline__ void scc_txint(struct scc_channel *scc)
/* External/Status interrupt handler */
-extern __inline__ void scc_exint(struct scc_channel *scc)
+static inline void scc_exint(struct scc_channel *scc)
{
unsigned char status,changes,chg_and_stat;
@@ -461,35 +477,39 @@ extern __inline__ void scc_exint(struct scc_channel *scc)
if (chg_and_stat & BRK_ABRT) /* Received an ABORT */
flush_rx_FIFO(scc);
+ /* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
+
+ if ((changes & SYNC_HUNT) && scc->kiss.softdcd)
+ {
+ if (status & SYNC_HUNT)
+ {
+ scc->dcd = 0;
+ flush_rx_FIFO(scc);
+ if ((scc->modem.clocksrc != CLK_EXTERNAL))
+ OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
+ } else {
+ scc->dcd = 1;
+ }
+
+ scc_notify(scc, scc->dcd? HWEV_DCD_OFF:HWEV_DCD_ON);
+ }
/* DCD: on = start to receive packet, off = ABORT condition */
/* (a successfully received packet generates a special condition int) */
- if(changes & DCD) /* DCD input changed state */
+ if((changes & DCD) && !scc->kiss.softdcd) /* DCD input changed state */
{
if(status & DCD) /* DCD is now ON */
{
- if (scc->modem.clocksrc != CLK_EXTERNAL)
- OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
-
- or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
+ start_hunt(scc);
+ scc->dcd = 1;
} else { /* DCD is now OFF */
cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
flush_rx_FIFO(scc);
+ scc->dcd = 0;
}
- if (!scc->kiss.softdcd)
- scc_notify(scc, (status & DCD)? HWEV_DCD_ON:HWEV_DCD_OFF);
- }
-
- /* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
-
- if (changes & SYNC_HUNT)
- {
- if (scc->kiss.softdcd)
- scc_notify(scc, (status & SYNC_HUNT)? HWEV_DCD_OFF:HWEV_DCD_ON);
- else
- cl(scc,R15,SYNCIE); /* oops, we were too lazy to disable this? */
+ scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
}
#ifdef notdef
@@ -527,7 +547,7 @@ extern __inline__ void scc_exint(struct scc_channel *scc)
/* Receiver interrupt handler */
-extern __inline__ void scc_rxint(struct scc_channel *scc)
+static inline void scc_rxint(struct scc_channel *scc)
{
struct sk_buff *skb;
@@ -575,7 +595,7 @@ extern __inline__ void scc_rxint(struct scc_channel *scc)
/* Receive Special Condition interrupt handler */
-extern __inline__ void scc_spint(struct scc_channel *scc)
+static inline void scc_spint(struct scc_channel *scc)
{
unsigned char status;
struct sk_buff *skb;
@@ -646,8 +666,6 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
struct scc_ctrl *ctrl;
int k;
- scc_cli(irq);
-
if (Vector_Latch)
{
for(k=0; k < SCC_IRQTIMEOUT; k++)
@@ -665,7 +683,6 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
OutReg(scc->ctrl,R0,RES_H_IUS); /* Reset Highest IUS */
}
- scc_sti(irq);
if (k == SCC_IRQTIMEOUT)
printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
@@ -718,8 +735,6 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
} else
ctrl++;
}
-
- scc_sti(irq);
}
@@ -731,7 +746,7 @@ static void scc_isr(int irq, void *dev_id, struct pt_regs *regs)
/* ----> set SCC channel speed <---- */
-extern __inline__ void set_brg(struct scc_channel *scc, unsigned int tc)
+static inline void set_brg(struct scc_channel *scc, unsigned int tc)
{
cl(scc,R14,BRENABL); /* disable baudrate generator */
wr(scc,R12,tc & 255); /* brg rate LOW */
@@ -739,7 +754,7 @@ extern __inline__ void set_brg(struct scc_channel *scc, unsigned int tc)
or(scc,R14,BRENABL); /* enable baudrate generator */
}
-extern __inline__ void set_speed(struct scc_channel *scc)
+static inline void set_speed(struct scc_channel *scc)
{
disable_irq(scc->irq);
@@ -752,7 +767,7 @@ extern __inline__ void set_speed(struct scc_channel *scc)
/* ----> initialize a SCC channel <---- */
-extern __inline__ void init_brg(struct scc_channel *scc)
+static inline void init_brg(struct scc_channel *scc)
{
wr(scc, R14, BRSRC); /* BRG source = PCLK */
OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]); /* DPLL source = BRG */
@@ -875,19 +890,15 @@ static void init_channel(struct scc_channel *scc)
wr(scc,R7,AUTOEOM);
}
- if((InReg(scc->ctrl,R0)) & DCD) /* DCD is now ON */
+ if(scc->kiss.softdcd || (InReg(scc->ctrl,R0) & DCD))
+ /* DCD is now ON */
{
- if (scc->modem.clocksrc != CLK_EXTERNAL)
- or(scc,R14, SEARCH);
-
- or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
+ start_hunt(scc);
}
/* enable ABORT, DCD & SYNC/HUNT interrupts */
- wr(scc,R15, BRKIE|TxUIE|DCDIE);
- if (scc->kiss.softdcd)
- or(scc,R15, SYNCIE);
+ wr(scc,R15, BRKIE|TxUIE|(scc->kiss.softdcd? SYNCIE:DCDIE));
Outb(scc->ctrl,RES_EXT_INT); /* reset ext/status interrupts */
Outb(scc->ctrl,RES_EXT_INT); /* must be done twice */
@@ -940,14 +951,21 @@ static void scc_key_trx(struct scc_channel *scc, char tx)
{
#ifdef CONFIG_SCC_TRXECHO
cl(scc, R3, RxENABLE|ENT_HM); /* switch off receiver */
- cl(scc, R15, DCDIE); /* No DCD changes, please */
+ cl(scc, R15, DCDIE|SYNCIE); /* No DCD changes, please */
#endif
set_brg(scc, time_const); /* reprogram baudrate generator */
/* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
- or(scc,R5,RTS|TxENAB); /* set the RTS line and enable TX */
+ /* By popular demand: tx_inhibit */
+ if (scc->kiss.tx_inhibit)
+ {
+ or(scc,R5, TxENAB);
+ scc->wreg[R5] |= RTS;
+ } else {
+ or(scc,R5,RTS|TxENAB); /* set the RTS line and enable TX */
+ }
} else {
cl(scc,R5,RTS|TxENAB);
@@ -955,10 +973,14 @@ static void scc_key_trx(struct scc_channel *scc, char tx)
/* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-#ifdef CONFIG_SCC_TRXECHO
- or(scc,R3,RxENABLE|ENT_HM);
- or(scc,R15, DCDIE);
+
+#ifndef CONFIG_SCC_TRXECHO
+ if (scc->kiss.softdcd)
#endif
+ {
+ or(scc,R15, scc->kiss.softdcd? SYNCIE:DCDIE);
+ start_hunt(scc);
+ }
}
} else {
if (tx)
@@ -967,22 +989,30 @@ static void scc_key_trx(struct scc_channel *scc, char tx)
if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
{
cl(scc, R3, RxENABLE);
- cl(scc, R15, DCDIE);
+ cl(scc, R15, DCDIE|SYNCIE);
}
#endif
-
- or(scc,R5,RTS|TxENAB); /* enable tx */
+ if (scc->kiss.tx_inhibit)
+ {
+ or(scc,R5, TxENAB);
+ scc->wreg[R5] |= RTS;
+ } else {
+ or(scc,R5,RTS|TxENAB); /* enable tx */
+ }
} else {
cl(scc,R5,RTS|TxENAB); /* disable tx */
-#ifdef CONFIG_SCC_TRXECHO
- if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+ if ((scc->kiss.fulldup == KISS_DUPLEX_HALF) &&
+#ifndef CONFIG_SCC_TRXECHO
+ scc->kiss.softdcd)
+#else
+ 1)
+#endif
{
- or(scc, R3, RxENABLE|ENT_HM);
- or(scc, R15, DCDIE);
+ or(scc, R15, scc->kiss.softdcd? SYNCIE:DCDIE);
+ start_hunt(scc);
}
-#endif
}
}
@@ -1088,7 +1118,7 @@ static void scc_tx_done(struct scc_channel *scc)
static unsigned char Rand = 17;
-extern __inline__ int is_grouped(struct scc_channel *scc)
+static inline int is_grouped(struct scc_channel *scc)
{
int k;
struct scc_channel *scc2;
@@ -1109,7 +1139,7 @@ extern __inline__ int is_grouped(struct scc_channel *scc)
if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
return 1;
- if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
+ if ( (grp1 & RXGROUP) && scc2->dcd )
return 1;
}
}
@@ -1144,7 +1174,7 @@ static void t_dwait(unsigned long channel)
{
Rand = Rand * 17 + 31;
- if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD)) || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
+ if (scc->dcd || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
{
scc_start_defer(scc);
scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);
@@ -1317,8 +1347,6 @@ static void scc_init_timer(struct scc_channel *scc)
static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)
{
- int dcd;
-
switch (cmd)
{
case PARAM_TXDELAY: scc->kiss.txdelay=arg; break;
@@ -1338,9 +1366,14 @@ static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, uns
case PARAM_SOFTDCD:
scc->kiss.softdcd=arg;
if (arg)
+ {
or(scc, R15, SYNCIE);
- else
+ cl(scc, R15, DCDIE);
+ start_hunt(scc);
+ } else {
+ or(scc, R15, DCDIE);
cl(scc, R15, SYNCIE);
+ }
break;
case PARAM_SPEED:
@@ -1369,8 +1402,7 @@ static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, uns
break;
case PARAM_HWEVENT:
- dcd = (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD));
- scc_notify(scc, dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
+ scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
break;
default: return -EINVAL;
@@ -1449,9 +1481,10 @@ scc_start_calibrate(struct scc_channel *scc, int duration, unsigned char pattern
scc->tx_wdog.data = (unsigned long) scc;
scc->tx_wdog.function = scc_stop_calibrate;
- scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
+ scc->tx_wdog.expires = jiffies + HZ*duration;
add_timer(&scc->tx_wdog);
-
+
+ /* This doesn't seem to work. Why not? */
wr(scc, R6, 0);
wr(scc, R7, pattern);
@@ -1680,6 +1713,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
skb->dev = scc->dev;
skb->protocol = htons(ETH_P_AX25);
skb->mac.raw = skb->data;
+ skb->pkt_type = PACKET_HOST;
netif_rx(skb);
return;
@@ -1722,7 +1756,7 @@ static int scc_net_tx(struct sk_buff *skb, struct device *dev)
save_flags(flags);
cli();
- if (skb_queue_len(&scc->tx_queue) >= MAXQUEUE-1)
+ if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len)
{
struct sk_buff *skb_del;
skb_del = __skb_dequeue(&scc->tx_queue);
@@ -1791,7 +1825,7 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
if (!suser()) return -EPERM;
if (!arg) return -EFAULT;
- if (Nchips >= MAXSCC)
+ if (Nchips >= SCC_MAXCHIPS)
return -EINVAL;
if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))
@@ -1811,14 +1845,15 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
Vector_Latch = hwcfg.vector_latch;
if (hwcfg.clock == 0)
- hwcfg.clock = DEFAULT_CLOCK;
+ hwcfg.clock = SCC_DEFAULT_CLOCK;
-#ifndef DONT_CHECK
+#ifndef SCC_DONT_CHECK
disable_irq(hwcfg.irq);
check_region(scc->ctrl, 1);
Outb(hwcfg.ctrl_a, 0);
- udelay(5);
+ OutReg(hwcfg.ctrl_a, R9, FHWRES);
+ udelay(100);
OutReg(hwcfg.ctrl_a,R13,0x55); /* is this chip really there? */
udelay(5);
@@ -1853,7 +1888,7 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
SCC_Info[2*Nchips+chan].option = hwcfg.option;
SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
-#ifdef DONT_CHECK
+#ifdef SCC_DONT_CHECK
printk(KERN_INFO "%s: data port = 0x%3.3x control port = 0x%3.3x\n",
device_name,
SCC_Info[2*Nchips+chan].data,
@@ -1903,7 +1938,7 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
if (!suser()) return -EPERM;
if (!arg) return -EINVAL;
- scc->stat.bufsize = BUFSIZE;
+ scc->stat.bufsize = SCC_BUFSIZE;
if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))
return -EINVAL;
@@ -1980,7 +2015,7 @@ static int scc_net_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
case SIOCSCCCAL:
if (!suser()) return -EPERM;
- if (!arg || copy_from_user(&cal, arg, sizeof(cal)))
+ if (!arg || copy_from_user(&cal, arg, sizeof(cal)) || cal.time == 0)
return -EINVAL;
scc_start_calibrate(scc, cal.time, cal.pattern);
@@ -2169,7 +2204,7 @@ __initfunc(int scc_init (void))
/* pre-init channel information */
- for (chip = 0; chip < MAXSCC; chip++)
+ for (chip = 0; chip < SCC_MAXCHIPS; chip++)
{
memset((char *) &SCC_Info[2*chip ], 0, sizeof(struct scc_channel));
memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
diff --git a/drivers/net/hamradio/soundmodem/sm.c b/drivers/net/hamradio/soundmodem/sm.c
index d1760af4b..15b5239fd 100644
--- a/drivers/net/hamradio/soundmodem/sm.c
+++ b/drivers/net/hamradio/soundmodem/sm.c
@@ -61,6 +61,7 @@
#include <asm/bitops.h>
#include <linux/delay.h>
#include <linux/errno.h>
+#include <linux/version.h>
#include "sm.h"
/* --------------------------------------------------------------------- */
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 55506e0ef..bcb76242a 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -474,7 +474,6 @@ cleanup_module(void)
void *priv = dev->priv;
/* NB: hpp_close() handles free_irq */
release_region(ioaddr, HP_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index a7dcba56b..8963b5562 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -445,7 +445,6 @@ cleanup_module(void)
void *priv = dev->priv;
free_irq(dev->irq, dev);
release_region(ioaddr, HP_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 4b415d6cc..5ac9da0a3 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1365,7 +1365,7 @@ static void hp100_init_pdls( struct device *dev )
/* They return how much memory the fragments need. */
static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
{
- /* pdlptr is starting adress for this pdl */
+ /* pdlptr is starting address for this pdl */
if( 0!=( ((unsigned)pdlptr) & 0xf) )
printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned)pdlptr);
@@ -2796,9 +2796,9 @@ static int hp100_down_vg_link( struct device *dev )
time=jiffies+(HZ/4);
do{
if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break;
- } while (time>jiffies);
+ } while (time_after(time, jiffies));
- if ( jiffies >= time ) /* no signal->no logout */
+ if ( time_after_eq(jiffies, time) ) /* no signal->no logout */
return 0;
/* Drop the VG Link by clearing the link up cmd and load addr.*/
@@ -2810,10 +2810,10 @@ static int hp100_down_vg_link( struct device *dev )
time=jiffies+(HZ/2);
do{
if ( !(hp100_inb( VG_LAN_CFG_1) & HP100_LINK_UP_ST) ) break;
- } while(time>jiffies);
+ } while(time_after(time, jiffies));
#ifdef HP100_DEBUG
- if (jiffies>=time)
+ if (time_after_eq(jiffies, time))
printk("hp100: %s: down_vg_link: Link does not go down?\n", dev->name);
#endif
@@ -2848,7 +2848,7 @@ static int hp100_down_vg_link( struct device *dev )
time=jiffies+(HZ*5);
do{
if( !(hp100_inb(MAC_CFG_4) & HP100_MAC_SEL_ST) ) break;
- } while(time>jiffies);
+ } while(time_after(time, jiffies));
hp100_orb( HP100_AUTO_MODE, MAC_CFG_3); /* Autosel back on */
hp100_outl(savelan, 10_LAN_CFG_1);
@@ -2857,9 +2857,9 @@ static int hp100_down_vg_link( struct device *dev )
time=jiffies+(3*HZ); /* Timeout 3s */
do {
if ( (hp100_inb( VG_LAN_CFG_1 )&HP100_LINK_CABLE_ST) == 0) break;
- } while (time>jiffies);
+ } while (time_after(time, jiffies));
- if(time<=jiffies)
+ if(time_before_eq(time, jiffies))
{
#ifdef HP100_DEBUG
printk( "hp100: %s: down_vg_link: timeout\n", dev->name );
@@ -2868,7 +2868,7 @@ static int hp100_down_vg_link( struct device *dev )
}
time=jiffies+(2*HZ); /* This seems to take a while.... */
- do {} while (time>jiffies);
+ do {} while (time_after(time, jiffies));
return 0;
}
@@ -2918,7 +2918,7 @@ static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin )
time = jiffies + (HZ/10);
do {
if (~(hp100_inb( VG_LAN_CFG_1 )& HP100_LINK_UP_ST) ) break;
- } while (time>jiffies);
+ } while (time_after(time, jiffies));
/* Start an addressed training and optionally request promiscuous port */
if ( (dev->flags) & IFF_PROMISC )
@@ -2955,9 +2955,9 @@ static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin )
time = jiffies + ( 1*HZ ); /* 1 sec timeout for cable st */
do {
if ( hp100_inb( VG_LAN_CFG_1 ) & HP100_LINK_CABLE_ST ) break;
- } while ( jiffies < time );
+ } while ( time_before(jiffies, time) );
- if ( jiffies >= time )
+ if ( time_after_eq(jiffies, time) )
{
#ifdef HP100_DEBUG_TRAINING
printk( "hp100: %s: Link cable status not ok? Training aborted.\n", dev->name );
@@ -2979,11 +2979,11 @@ static int hp100_login_to_vg_hub( struct device *dev, u_short force_relogin )
#endif
break;
}
- } while ( time > jiffies );
+ } while ( time_after(time, jiffies) );
}
/* If LINK_UP_ST is set, then we are logged into the hub. */
- if ( (jiffies<=time) && (val & HP100_LINK_UP_ST) )
+ if ( time_before_eq(jiffies, time) && (val & HP100_LINK_UP_ST) )
{
#ifdef HP100_DEBUG_TRAINING
printk( "hp100: %s: Successfully logged into the HUB.\n", dev->name);
diff --git a/drivers/net/ibmtr.c b/drivers/net/ibmtr.c
index f781abbf3..990610648 100644
--- a/drivers/net/ibmtr.c
+++ b/drivers/net/ibmtr.c
@@ -66,8 +66,17 @@
* + lifted 2000 byte mtu limit. now depends on shared-RAM size.
* May 25 1998)
* + can't allocate 2k recv buff at 8k shared-RAM. (20 October 1998)
+ *
+ * Changes by Joel Sloan (jjs@c-me.com) :
+ * + disable verbose debug messages by default - to enable verbose
+ * debugging, edit the IBMTR_DEBUG_MESSAGES define below
*/
+/* change the define of IBMTR_DEBUG_MESSAGES to a nonzero value
+in the event that chatty debug messages are desired - jjs 12/30/98 */
+
+#define IBMTR_DEBUG_MESSAGES 0
+
#ifdef PCMCIA
#define MODULE
#endif
@@ -95,7 +104,8 @@
/* version and credits */
static char *version =
"ibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n"
-" v2.1.125 10/20/98 Paul Norton <pnorton@ieee.org>\n";
+" v2.1.125 10/20/98 Paul Norton <pnorton@ieee.org>\n"
+" v2.2.0 12/30/98 Joel Sloan <jjs@c-me.com>\n";
static char pcchannelid[] = {
0x05, 0x00, 0x04, 0x09,
@@ -791,10 +801,10 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
struct tok_info *ti;
struct device *dev;
+ dev = dev_id;
#if TR_VERBOSE
DPRINTK("Int from tok_driver, dev : %p\n",dev);
#endif
- dev = dev_id;
ti = (struct tok_info *) dev->priv;
/* Disable interrupts till processing is finished */
@@ -999,6 +1009,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
DPRINTK("error on dir_read_log: %02X\n",
(int)readb(ti->srb+offsetof(struct srb_read_log, ret_code)));
else
+ if (IBMTR_DEBUG_MESSAGES) {
DPRINTK(
"Line errors %02X, Internal errors %02X, Burst errors %02X\n"
"A/C errors %02X, Abort delimiters %02X, Lost frames %02X\n"
@@ -1023,6 +1034,7 @@ void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs)
frequency_errors)),
(int)readb(ti->srb+offsetof(struct srb_read_log,
token_errors)));
+ }
dev->tbusy=0;
break;
@@ -1230,7 +1242,7 @@ static int tok_init_card(struct device *dev)
{
struct tok_info *ti;
short PIOaddr;
- int i;
+ unsigned long i;
PIOaddr = dev->base_addr;
ti=(struct tok_info *) dev->priv;
@@ -1252,7 +1264,7 @@ static int tok_init_card(struct device *dev)
#endif
outb(0, PIOaddr+ADAPTRESET);
- for (i=jiffies+TR_RESET_INTERVAL; jiffies<=i;); /* wait 50ms */
+ for (i=jiffies+TR_RESET_INTERVAL; time_before_eq(jiffies, i);); /* wait 50ms */
outb(0,PIOaddr+ADAPTRESETREL);
#if !TR_NEWFORMAT
diff --git a/drivers/net/irda/.cvsignore b/drivers/net/irda/.cvsignore
new file mode 100644
index 000000000..857dd22e9
--- /dev/null
+++ b/drivers/net/irda/.cvsignore
@@ -0,0 +1,2 @@
+.depend
+.*.flags
diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in
new file mode 100644
index 000000000..c40b6f5c8
--- /dev/null
+++ b/drivers/net/irda/Config.in
@@ -0,0 +1,17 @@
+mainmenu_option next_comment
+comment 'Infrared-port device drivers'
+
+dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
+if [ "$CONFIG_IRTTY_SIR" != "n" ]; then
+ comment ' Dongle support'
+ bool ' Serial dongle support' CONFIG_DONGLE
+ if [ "$CONFIG_DONGLE" != "n" ]; then
+ dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR
+ dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR
+ dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR
+ fi
+fi
+dep_tristate ' NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA
+dep_tristate ' Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+dep_tristate ' Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
+endmenu
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
new file mode 100644
index 000000000..05880d5e1
--- /dev/null
+++ b/drivers/net/irda/Makefile
@@ -0,0 +1,80 @@
+# File: drivers/irda/Makefile
+#
+# Makefile for the Linux IrDA infrared port device drivers.
+#
+
+SUB_DIRS :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+L_TARGET := irda_drivers.a
+L_OBJS :=
+M_OBJS :=
+MOD_LIST_NAME := IRDA_MODULES
+
+ifeq ($(CONFIG_IRTTY_SIR),y)
+L_OBJS += irtty.o
+else
+ ifeq ($(CONFIG_IRTTY_SIR),m)
+ M_OBJS += irtty.o
+ endif
+endif
+
+ifeq ($(CONFIG_NSC_FIR),y)
+L_OBJS += pc87108.o
+else
+ ifeq ($(CONFIG_NSC_FIR),m)
+ M_OBJS += pc87108.o
+ endif
+endif
+
+ifeq ($(CONFIG_WINBOND_FIR),y)
+L_OBJS += w83977af_ir.o
+else
+ ifeq ($(CONFIG_WINBOND_FIR),m)
+ M_OBJS += w83977af_ir.o
+ endif
+endif
+
+ifeq ($(CONFIG_SHARP_FIR),y)
+L_OBJS += uircc.o irport.o
+else
+ ifeq ($(CONFIG_SHARP_FIR),m)
+ M_OBJS += uircc.o irport.o
+ endif
+endif
+
+ifeq ($(CONFIG_ESI_DONGLE),y)
+L_OBJS += esi.o
+else
+ ifeq ($(CONFIG_ESI_DONGLE),m)
+ M_OBJS += esi.o
+ endif
+endif
+
+ifeq ($(CONFIG_TEKRAM_DONGLE),y)
+L_OBJS += tekram.o
+else
+ ifeq ($(CONFIG_TEKRAM_DONGLE),m)
+ M_OBJS += tekram.o
+ endif
+endif
+
+ifeq ($(CONFIG_ACTISYS_DONGLE),y)
+L_OBJS += actisys.o
+else
+ ifeq ($(CONFIG_ACTISYS_DONGLE),m)
+ M_OBJS += actisys.o
+ endif
+endif
+
+include $(TOPDIR)/Rules.make
+
+clean:
+ rm -f core *.o *.a *.s
+
+
+
+
+
+
diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c
new file mode 100644
index 000000000..97fb5fa27
--- /dev/null
+++ b/drivers/net/irda/actisys.c
@@ -0,0 +1,314 @@
+/*********************************************************************
+ *
+ * Filename: actisys.c
+ * Version: 0.4
+ * Description: Implementation for the ACTiSYS IR-220L and IR-220L+
+ * dongles
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Wed Oct 21 20:02:35 1998
+ * Modified at: Mon Jan 18 11:30:25 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irtty.h>
+#include <net/irda/dongle.h>
+
+static void actisys_reset( struct irda_device *dev, int unused);
+static void actisys_open( struct irda_device *idev, int type);
+static void actisys_close( struct irda_device *dev);
+static void actisys_change_speed( struct irda_device *dev, int baudrate);
+static void actisys_reset( struct irda_device *dev, int unused);
+static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos);
+
+/* These are the baudrates supported */
+static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
+
+static struct dongle dongle = {
+ ACTISYS_DONGLE,
+ actisys_open,
+ actisys_close,
+ actisys_reset,
+ actisys_change_speed,
+ actisys_init_qos,
+};
+
+__initfunc(void actisys_init(void))
+{
+ irtty_register_dongle(&dongle);
+}
+
+void actisys_cleanup(void)
+{
+ irtty_unregister_dongle(&dongle);
+}
+
+static void actisys_open( struct irda_device *idev, int type)
+{
+ strcat( idev->name, " <-> actisys");
+
+ idev->io.dongle_id = type;
+
+ MOD_INC_USE_COUNT;
+}
+
+static void actisys_close( struct irda_device *dev)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function actisys_change_speed (tty, baud)
+ *
+ * Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
+ * To cycle through the available baud rates, pulse RTS low for a few ms.
+ * To be compatible with the new IR-220L+, we have to reset the dongle
+ * first since its not possible cycle around anymore and still be
+ * compatible with both dongles :-(
+ */
+static void actisys_change_speed( struct irda_device *idev, int baudrate)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ int arg;
+ struct termios old_termios;
+ int cflag;
+ int current_baudrate;
+ int index = 0;
+ mm_segment_t fs;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ current_baudrate = idev->qos.baud_rate.value;
+
+ /* Find the correct baudrate index for the currently used baudrate */
+ while ( current_baudrate != baud_rates[index])
+ index++;
+
+ DEBUG( 0, __FUNCTION__ "(), index=%d\n", index);
+
+ if ( !self->tty)
+ return;
+
+ tty = self->tty;
+
+ /* Cycle through avaiable baudrates until we reach the correct one */
+ while ( current_baudrate != baudrate) {
+ DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+ baud_rates[index]);
+ DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
+
+ /* Set DTR, clear RTS */
+ arg = TIOCM_DTR|TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg)) {
+ DEBUG( 0, __FUNCTION__
+ "Error clearing RTS!\n");
+ }
+ set_fs(fs);
+
+ /* Wait at a few ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ /* Set DTR, Set RTS */
+ arg = TIOCM_DTR | TIOCM_RTS |TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg)) {
+ DEBUG( 0, __FUNCTION__ "Error setting RTS!\n");
+ }
+ set_fs(fs);
+
+ /* Wait at a few ms again */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout( 2);
+
+ /* Go to next baudrate */
+ if ( idev->io.dongle_id == ACTISYS_DONGLE)
+ index = (index+1) % 4; /* IR-220L */
+ else
+ index = (index+1) % 5; /* IR-220L+ */
+
+ current_baudrate = baud_rates[index];
+ }
+ DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+ baud_rates[index]);
+
+ /* Now change the speed of the serial port */
+ old_termios = *(tty->termios);
+ cflag = tty->termios->c_cflag;
+
+ cflag &= ~CBAUD;
+
+ switch ( baudrate) {
+ case 9600:
+ default:
+ cflag |= B9600;
+ break;
+ case 19200:
+ cflag |= B19200;
+ break;
+ case 38400:
+ cflag |= B38400;
+ break;
+ case 57600:
+ cflag |= B57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ break;
+ }
+
+ tty->termios->c_cflag = cflag;
+
+ DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n");
+ tty->driver.set_termios( tty, &old_termios);
+}
+
+/*
+ * Function actisys_reset (dev)
+ *
+ * Reset the Actisys type dongle. Warning, this function must only be
+ * called with a process context!
+ *
+ * 1. Clear DTR for a few ms.
+ *
+ */
+static void actisys_reset( struct irda_device *idev, int unused)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ int arg = 0;
+ mm_segment_t fs;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ tty = self->tty;
+ if ( !tty)
+ return;
+
+ DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
+ arg = TIOCM_RTS | TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg))
+ {
+ DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
+ }
+ set_fs(fs);
+
+ /* Sleep 10-20 ms*/
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
+ arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg))
+ {
+ DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
+ }
+ set_fs(fs);
+
+ idev->qos.baud_rate.value = 9600;
+}
+
+/*
+ * Function actisys_init_qos (qos)
+ *
+ * Initialize QoS capabilities
+ *
+ */
+static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos)
+{
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+
+ /* Remove support for 38400 if this is not a 220L+ dongle */
+ if ( idev->io.dongle_id == ACTISYS_DONGLE)
+ qos->baud_rate.bits &= ~IR_38400;
+
+ qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize Actisys module
+ *
+ */
+int init_module(void)
+{
+ actisys_init();
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup Actisys module
+ *
+ */
+void cleanup_module(void)
+{
+ actisys_cleanup();
+}
+
+#endif
diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c
new file mode 100644
index 000000000..a93e167aa
--- /dev/null
+++ b/drivers/net/irda/esi.c
@@ -0,0 +1,194 @@
+/*********************************************************************
+ *
+ * Filename: esi.c
+ * Version: 1.1
+ * Description: Driver for the Extended Systems JetEye PC
+ * Status: Experimental.
+ * Author: Thomas Davis, <ratbert@radiks.net>
+ * Created at: Sat Feb 21 18:54:38 1998
+ * Modified at: Mon Jan 18 11:30:32 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ * Sources: esi.c
+ *
+ * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
+ * Copyright (c) 1998, Dag Brattli, <dagb@cs.uit.no>
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * I, Thomas Davis, provide no warranty for any of this software.
+ * This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irtty.h>
+#include <net/irda/dongle.h>
+
+static void esi_open( struct irda_device *idev, int type);
+static void esi_close( struct irda_device *driver);
+static void esi_change_speed( struct irda_device *idev, int baud);
+static void esi_reset( struct irda_device *idev, int unused);
+static void esi_qos_init( struct irda_device *idev, struct qos_info *qos);
+
+static struct dongle dongle = {
+ ESI_DONGLE,
+ esi_open,
+ esi_close,
+ esi_reset,
+ esi_change_speed,
+ esi_qos_init,
+};
+
+__initfunc(void esi_init(void))
+{
+ irtty_register_dongle( &dongle);
+}
+
+void esi_cleanup(void)
+{
+ irtty_unregister_dongle( &dongle);
+}
+
+static void esi_open( struct irda_device *idev, int type)
+{
+ strcat( idev->description, " <-> esi");
+
+ idev->io.dongle_id = type;
+
+ MOD_INC_USE_COUNT;
+}
+
+static void esi_close( struct irda_device *driver)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function esi_change_speed (tty, baud)
+ *
+ * Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
+ *
+ */
+static void esi_change_speed( struct irda_device *idev, int baud)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ int arg = TIOCM_OUT2;
+ struct termios old_termios;
+ int cflag;
+ mm_segment_t fs;
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ if ( !self->tty)
+ return;
+
+ tty = self->tty;
+
+ old_termios = *(tty->termios);
+ cflag = tty->termios->c_cflag;
+
+ cflag &= ~CBAUD;
+
+ switch (baud) {
+ case 19200:
+ cflag |= B19200;
+ arg |= TIOCM_DTR;
+ break;
+ case 115200:
+ cflag |= B115200;
+ arg |= TIOCM_RTS | TIOCM_DTR;
+ break;
+ case 9600:
+ default:
+ cflag |= B9600;
+ arg |= TIOCM_RTS;
+ break;
+ }
+
+ tty->termios->c_cflag = cflag;
+ tty->driver.set_termios( tty, &old_termios);
+
+ /*
+ * The ioctl function, or actually set_modem_info in serial.c
+ * expects a pointer to the argument in user space. To hack us
+ * around this we use the set_fs function to fool the routines
+ * that check if they are called from user space. We also need
+ * to send a pointer to the argument so get_user() gets happy.
+ * DB.
+ */
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) {
+ DEBUG( 0, __FUNCTION__ "(), error setting ESI speed!\n");
+ }
+ set_fs(fs);
+}
+
+static void esi_reset( struct irda_device *idev, int unused)
+{
+ /* Empty */
+}
+
+/*
+ * Function esi_qos_init (qos)
+ *
+ * Init QoS capabilities for the dongle
+ *
+ */
+static void esi_qos_init( struct irda_device *idev, struct qos_info *qos)
+{
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize ESI module
+ *
+ */
+int init_module(void)
+{
+ esi_init();
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup ESI module
+ *
+ */
+void cleanup_module(void)
+{
+ esi_cleanup();
+}
+
+#endif
+
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
new file mode 100644
index 000000000..ae8bcb27b
--- /dev/null
+++ b/drivers/net/irda/irport.c
@@ -0,0 +1,403 @@
+/*********************************************************************
+ *
+ * Filename: irport.c
+ * Version: 0.8
+ * Description: Serial driver for IrDA.
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 3 13:49:59 1997
+ * Modified at: Sat May 23 23:15:20 1998
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ * Sources: serial.c by Linus Torvalds
+ * serial_serial.c by Aage Kvalnes <aage@cs.uit.no>
+ *
+ * Copyright (c) 1997,1998 Dag Brattli <dagb@cs.uit.no>
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * NOTICE:
+ *
+ * This driver is ment to be a small serial driver to be used for
+ * IR-chipsets that has a UART (16550) compatibility mode. If your
+ * chipset is is UART only, you should probably use IrTTY instead since
+ * the Linux serial driver is probably more robust and optimized.
+ *
+ * The functions in this file may be used by FIR drivers, but this
+ * driver knows nothing about FIR drivers so don't ever insert such
+ * code into this file. Instead you should code your FIR driver in a
+ * separate file, and then call the functions in this file if
+ * necessary. This is becase it is difficult to use the Linux serial
+ * driver with a FIR driver becase they must share interrupts etc. Most
+ * FIR chipsets can function in advanced SIR mode, and you should
+ * probably use that mode instead of the UART compatibility mode (and
+ * then just forget about this file)
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <linux/skbuff.h>
+#include <linux/serial_reg.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irport.h>
+
+#define IO_EXTENT 8
+
+static unsigned int io[] = { 0x3e8, ~0, ~0, ~0 };
+static unsigned int irq[] = { 11, 0, 0, 0 };
+
+static void irport_write_wakeup( struct irda_device *idev);
+static int irport_write( int iobase, int fifo_size, __u8 *buf, int len);
+static void irport_receive( struct irda_device *idev);
+
+__initfunc(int irport_init(void))
+{
+/* int i; */
+
+/* for ( i=0; (io[i] < 2000) && (i < 4); i++) { */
+/* int ioaddr = io[i]; */
+/* if (check_region(ioaddr, IO_EXTENT)) */
+/* continue; */
+/* if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */
+/* return 0; */
+/* } */
+/* return -ENODEV; */
+ return 0;
+}
+
+/*
+ * Function pc87108_cleanup ()
+ *
+ * Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void irport_cleanup(void)
+{
+ int i;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* for ( i=0; i < 4; i++) { */
+/* if ( dev_self[i]) */
+/* irport_close( &(dev_self[i]->idev)); */
+/* } */
+}
+#endif /* MODULE */
+
+/*
+ * Function irport_open (void)
+ *
+ * Start IO port
+ *
+ */
+int irport_open( int iobase)
+{
+ DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
+ /* Initialize UART */
+ outb( UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
+ outb(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
+
+ /* Turn on interrups */
+ outb(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER);
+
+ return 0;
+}
+
+/*
+ * Function irport_cleanup ()
+ *
+ * Stop IO port
+ *
+ */
+void irport_close( int iobase)
+{
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ /* Reset UART */
+ outb( 0, iobase+UART_MCR);
+
+ /* Turn off interrupts */
+ outb( 0, iobase+UART_IER);
+}
+
+/*
+ * Function irport_change_speed (idev, speed)
+ *
+ * Set speed of port to specified baudrate
+ *
+ */
+void irport_change_speed( int iobase, int speed)
+{
+ int fcr; /* FIFO control reg */
+ int lcr; /* Line control reg */
+ int divisor;
+
+ DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+
+ DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
+ /* Turn off interrupts */
+ outb( 0, iobase+UART_IER);
+
+ divisor = SPEED_MAX/speed;
+
+ fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
+
+ /* IrDA ports use 8N1 */
+ lcr = UART_LCR_WLEN8;
+
+ outb( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
+ outb( divisor & 0xff, iobase+UART_DLL); /* Set speed */
+ outb( divisor >> 8, iobase+UART_DLM);
+ outb( lcr, iobase+UART_LCR); /* Set 8N1 */
+ outb( fcr, iobase+UART_FCR); /* Enable FIFO's */
+
+ /* Turn on interrups */
+ outb( UART_IER_THRI|UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER);
+}
+
+/*
+ * Function irport_interrupt (irq, dev_id, regs)
+ *
+ *
+ */
+void irport_interrupt( int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct irda_device *idev = (struct irda_device *) dev_id;
+
+ int iobase, status;
+ int iir;
+
+ DEBUG( 4, __FUNCTION__ "(), irq %d\n", irq);
+
+ if ( !idev) {
+ printk( KERN_WARNING __FUNCTION__
+ "() irq %d for unknown device.\n", irq);
+ return;
+ }
+
+ idev->netdev.interrupt = 1;
+
+ iobase = idev->io.iobase2;
+
+ iir = inb(iobase + UART_IIR);
+ do {
+ status = inb( iobase+UART_LSR);
+
+ if (status & UART_LSR_DR) {
+ /* Receive interrupt */
+ irport_receive(idev);
+ }
+ if (status & UART_LSR_THRE) {
+ /* Transmitter ready for data */
+ irport_write_wakeup(idev);
+ }
+ } while (!(inb(iobase+UART_IIR) & UART_IIR_NO_INT));
+
+ idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function irport_write_wakeup (tty)
+ *
+ * Called by the driver when there's room for more data. If we have
+ * more packets to send, we send them here.
+ *
+ */
+static void irport_write_wakeup( struct irda_device *idev)
+{
+ int actual = 0, count;
+
+ DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ /* Finished with frame? */
+ if ( idev->tx_buff.offset == idev->tx_buff.len) {
+
+ /*
+ * Now serial buffer is almost free & we can start
+ * transmission of another packet
+ */
+ DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->stats.tx_packets++;
+
+ /* Schedule network layer, so we can get some more frames */
+ mark_bh( NET_BH);
+
+ return;
+ }
+
+ /* Write data left in transmit buffer */
+ count = idev->tx_buff.len - idev->tx_buff.offset;
+ actual = irport_write( idev->io.iobase2, idev->io.fifo_size,
+ idev->tx_buff.head, count);
+ idev->tx_buff.offset += actual;
+ idev->tx_buff.head += actual;
+}
+
+/*
+ * Function irport_write (driver)
+ *
+ *
+ *
+ */
+static int irport_write( int iobase, int fifo_size, __u8 *buf, int len)
+{
+ int actual = 0;
+
+ /* Tx FIFO should be empty! */
+ if (!(inb( iobase+UART_LSR) & UART_LSR_THRE)) {
+ DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+ return -1;
+ }
+
+ /* Fill FIFO with current frame */
+ while (( fifo_size-- > 0) && (actual < len)) {
+ /* Transmit next byte */
+ outb( buf[actual], iobase+UART_TX);
+
+ actual++;
+ }
+
+ DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ fifo_size, actual, len);
+
+ return actual;
+}
+
+/*
+ * Function irport_xmit (void)
+ *
+ * Transmits the current frame until FIFO is full, then
+ * waits until the next transmitt interrupt, and continues until the
+ * frame is transmited.
+ */
+int irport_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+ struct irda_device *idev;
+ int xbofs;
+ int actual;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( dev != NULL, return -1;);
+
+ if ( dev->tbusy) {
+ DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+
+ return -EBUSY;
+ }
+
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ /* Lock transmit buffer */
+ if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ /*
+ * Transfer skb to tx_buff while wrapping, stuffing and making CRC
+ */
+ idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data,
+ idev->tx_buff.truesize);
+
+ actual = irport_write( idev->io.iobase2, idev->io.fifo_size,
+ idev->tx_buff.data, idev->tx_buff.len);
+
+ idev->tx_buff.offset = actual;
+ idev->tx_buff.head = idev->tx_buff.data + actual;
+
+ dev_kfree_skb( skb);
+
+ return 0;
+}
+
+/*
+ * Function irport_receive (void)
+ *
+ * Receive one frame from the infrared port
+ *
+ */
+static void irport_receive( struct irda_device *idev)
+{
+ int iobase;
+
+ if ( !idev)
+ return;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ iobase = idev->io.iobase2;
+
+ if ( idev->rx_buff.len == 0)
+ idev->rx_buff.head = idev->rx_buff.data;
+
+ /*
+ * Receive all characters in Rx FIFO, unwrap and unstuff them.
+ * async_unwrap_char will deliver all found frames
+ */
+ do {
+ async_unwrap_char( idev, inb( iobase+UART_RX));
+
+ } while ( inb( iobase+UART_LSR) & UART_LSR_DR);
+}
+
+#ifdef MODULE
+
+/*
+ * Function cleanup_module (void)
+ *
+ *
+ *
+ */
+void cleanup_module(void)
+{
+ irport_cleanup();
+}
+
+/*
+ * Function init_module (void)
+ *
+ *
+ */
+int init_module(void)
+{
+ if (irport_init() < 0) {
+ cleanup_module();
+ return 1;
+ }
+ return(0);
+}
+
+#endif /* MODULE */
+
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
new file mode 100644
index 000000000..09853b5b6
--- /dev/null
+++ b/drivers/net/irda/irtty.c
@@ -0,0 +1,748 @@
+/*********************************************************************
+ *
+ * Filename: irtty.c
+ * Version: 1.0
+ * Description: IrDA line discipline implementation
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Tue Dec 9 21:18:38 1997
+ * Modified at: Mon Jan 18 15:32:03 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ * Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
+ * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <asm/segment.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irtty.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irlap.h>
+#include <net/irda/timer.h>
+#include <net/irda/irda_device.h>
+#include <linux/kmod.h>
+
+static hashbin_t *irtty = NULL;
+static hashbin_t *dongles = NULL;
+
+static struct tty_ldisc irda_ldisc;
+
+static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev);
+static void irtty_wait_until_sent( struct irda_device *driver);
+static int irtty_is_receiving( struct irda_device *idev);
+static int irtty_net_init( struct device *dev);
+static int irtty_net_open(struct device *dev);
+static int irtty_net_close(struct device *dev);
+
+static int irtty_open( struct tty_struct *tty);
+static void irtty_close( struct tty_struct *tty);
+static int irtty_ioctl( struct tty_struct *, void *, int, void *);
+static int irtty_receive_room( struct tty_struct *tty);
+static void irtty_change_speed( struct irda_device *dev, int baud);
+static void irtty_write_wakeup( struct tty_struct *tty);
+
+static void irtty_receive_buf( struct tty_struct *, const unsigned char *,
+ char *, int);
+char *driver_name = "irtty";
+
+__initfunc(int irtty_init(void))
+{
+ int status;
+
+ irtty = hashbin_new( HB_LOCAL);
+ if ( irtty == NULL) {
+ printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n");
+ return -ENOMEM;
+ }
+
+ dongles = hashbin_new( HB_LOCAL);
+ if ( dongles == NULL) {
+ printk( KERN_WARNING
+ "IrDA: Can't allocate dongles hashbin!\n");
+ return -ENOMEM;
+ }
+
+ /* Fill in our line protocol discipline, and register it */
+ memset( &irda_ldisc, 0, sizeof( irda_ldisc));
+
+ irda_ldisc.magic = TTY_LDISC_MAGIC;
+ irda_ldisc.name = "irda";
+ irda_ldisc.flags = 0;
+ irda_ldisc.open = irtty_open;
+ irda_ldisc.close = irtty_close;
+ irda_ldisc.read = NULL;
+ irda_ldisc.write = NULL;
+ irda_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
+ unsigned int, unsigned long)) irtty_ioctl;
+ irda_ldisc.poll = NULL;
+ irda_ldisc.receive_buf = irtty_receive_buf;
+ irda_ldisc.receive_room = irtty_receive_room;
+ irda_ldisc.write_wakeup = irtty_write_wakeup;
+
+ if (( status = tty_register_ldisc( N_IRDA, &irda_ldisc)) != 0) {
+ printk( KERN_ERR
+ "IrDA: can't register line discipline (err = %d)\n",
+ status);
+ }
+
+ return status;
+}
+
+/*
+ * Function irtty_cleanup ( )
+ *
+ * Called when the irda module is removed. Here we remove all instances
+ * of the driver, and the master array.
+ */
+#ifdef MODULE
+static void irtty_cleanup(void)
+{
+ int ret;
+
+ /*
+ * Unregister tty line-discipline
+ */
+ if (( ret = tty_register_ldisc( N_IRDA, NULL))) {
+ printk( KERN_ERR
+ "IrTTY: can't unregister line discipline (err = %d)\n",
+ ret);
+ }
+
+ /*
+ * The TTY should care of deallocating the instances by using the
+ * callback to irtty_close(), therefore we do give any deallocation
+ * function to hashbin_destroy().
+ */
+ hashbin_delete( irtty, NULL);
+ hashbin_delete( dongles, NULL);
+}
+#endif /* MODULE */
+
+/*
+ * Function irtty_open(tty)
+ *
+ * This function is called by the TTY module when the IrDA line
+ * discipline is called for. Because we are sure the tty line exists,
+ * we only have to link it to a free IrDA channel.
+ */
+static int irtty_open( struct tty_struct *tty)
+{
+ struct irtty_cb *self;
+ char name[16];
+
+ ASSERT( tty != NULL, return -EEXIST;);
+
+ /* First make sure we're not already connected. */
+ self = (struct irtty_cb *) tty->disc_data;
+ if ( self != NULL && self->magic == IRTTY_MAGIC)
+ return -EEXIST;
+
+ /*
+ * Allocate new instance of the driver
+ */
+ self = kmalloc( sizeof(struct irtty_cb), GFP_KERNEL);
+ if ( self == NULL) {
+ printk( KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+ return -ENOMEM;
+ }
+ memset( self, 0, sizeof(struct irtty_cb));
+
+ self->tty = tty;
+ tty->disc_data = self;
+
+ /* Give self a name */
+ sprintf( name, "%s%d", tty->driver.name,
+ MINOR(tty->device) - tty->driver.minor_start +
+ tty->driver.name_base);
+
+ /* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */
+ hashbin_insert( irtty, (QUEUE*) self, (int) self, NULL);
+
+ if (tty->driver.flush_buffer) {
+ tty->driver.flush_buffer(tty);
+ }
+
+ if (tty->ldisc.flush_buffer) {
+ tty->ldisc.flush_buffer(tty);
+ }
+
+ self->magic = IRTTY_MAGIC;
+
+ /*
+ * Initialize driver
+ */
+ /* self->idev.flags |= SIR_MODE | IO_PIO; */
+ self->idev.rx_buff.state = OUTSIDE_FRAME;
+
+ /*
+ * Initialize QoS capabilities, we fill in all the stuff that
+ * we support. Be careful not to place any restrictions on values
+ * that are not device dependent (such as link disconnect time) so
+ * this parameter can be set by IrLAP (or the user) instead. DB
+ */
+ irda_init_max_qos_capabilies( &self->idev.qos);
+
+ /* The only value we must override it the baudrate */
+ self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200;
+ self->idev.qos.min_turn_time.bits = 0x03;
+ irda_qos_bits_to_value( &self->idev.qos);
+
+ /* Specify which buffer allocation policy we need */
+ self->idev.rx_buff.flags = GFP_KERNEL;
+ self->idev.tx_buff.flags = GFP_KERNEL;
+
+ /* Specify how much memory we want */
+ self->idev.rx_buff.truesize = 4000;
+ self->idev.tx_buff.truesize = 4000;
+
+ /* Initialize callbacks */
+ self->idev.change_speed = irtty_change_speed;
+ self->idev.is_receiving = irtty_is_receiving;
+ /* self->idev.is_tbusy = irtty_is_tbusy; */
+ self->idev.wait_until_sent = irtty_wait_until_sent;
+
+ /* Override the network functions we need to use */
+ self->idev.netdev.init = irtty_net_init;
+ self->idev.netdev.hard_start_xmit = irtty_hard_xmit;
+ self->idev.netdev.open = irtty_net_open;
+ self->idev.netdev.stop = irtty_net_close;
+
+ /* Open the IrDA device */
+ irda_device_open( &self->idev, name, self);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/*
+ * Function irtty_close ( tty)
+ *
+ * Close down a IrDA channel. This means flushing out any pending queues,
+ * and then restoring the TTY line discipline to what it was before it got
+ * hooked to IrDA (which usually is TTY again).
+ */
+static void irtty_close( struct tty_struct *tty)
+{
+ struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+
+ /* First make sure we're connected. */
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ /* We are not using any dongle anymore! */
+ if ( self->dongle_q)
+ self->dongle_q->dongle->close( &self->idev);
+
+ /* Remove driver */
+ irda_device_close( &self->idev);
+
+ /* Stop tty */
+ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ tty->disc_data = 0;
+
+ self->tty = NULL;
+ self->magic = 0;
+
+ /* hashbin_remove( irtty, 0, self->name); */
+ self = hashbin_remove( irtty, (int) self, NULL);
+
+ if ( self != NULL)
+ kfree( self);
+
+ MOD_DEC_USE_COUNT;
+
+ DEBUG( 4, "IrTTY: close() -->\n");
+}
+
+/*
+ * Function irtty_change_speed ( self, baud)
+ *
+ * Change the speed of the serial port. The driver layer must check that
+ * all transmission has finished using the irtty_wait_until_sent()
+ * function.
+ */
+static void irtty_change_speed( struct irda_device *idev, int baud)
+{
+ struct termios old_termios;
+ struct irtty_cb *self;
+ int cflag;
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ old_termios = *(self->tty->termios);
+ cflag = self->tty->termios->c_cflag;
+
+ cflag &= ~CBAUD;
+
+ DEBUG( 4, __FUNCTION__ "(), Setting speed to %d\n", baud);
+
+ switch( baud) {
+ case 1200:
+ cflag |= B1200;
+ break;
+ case 2400:
+ cflag |= B2400;
+ break;
+ case 4800:
+ cflag |= B4800;
+ break;
+ case 19200:
+ cflag |= B19200;
+ break;
+ case 38400:
+ cflag |= B38400;
+ break;
+ case 57600:
+ cflag |= B57600;
+ break;
+ case 115200:
+ cflag |= B115200;
+ break;
+ case 9600:
+ default:
+ cflag |= B9600;
+ break;
+ }
+
+ self->tty->termios->c_cflag = cflag;
+ self->tty->driver.set_termios( self->tty, &old_termios);
+}
+
+/*
+ * Function irtty_init_dongle (self, type)
+ *
+ * Initialize attached dongle. Warning, must be called with a process
+ * context!
+ */
+static void irtty_init_dongle( struct irtty_cb *self, int type)
+{
+ struct dongle_q *node;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+#ifdef CONFIG_KMOD
+ /* Try to load the module needed */
+ switch( type) {
+ case ESI_DONGLE:
+ DEBUG( 0, __FUNCTION__ "(), ESI dongle!\n");
+ request_module( "esi");
+ break;
+ case TEKRAM_DONGLE:
+ DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n");
+ request_module( "tekram");
+ break;
+ case ACTISYS_DONGLE:
+ DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n");
+ request_module( "actisys");
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n");
+ return;
+ break;
+ }
+#endif /* CONFIG_KMOD */
+
+ node = hashbin_find( dongles, type, NULL);
+ if ( !node) {
+ DEBUG( 0, __FUNCTION__
+ "(), Unable to find requested dongle\n");
+ return;
+ }
+ self->dongle_q = node;
+
+ /* Use this change speed function instead of the default */
+ self->idev.change_speed = node->dongle->change_speed;
+
+ /*
+ * Now initialize the dongle!
+ */
+ node->dongle->open( &self->idev, type);
+ node->dongle->qos_init( &self->idev, &self->idev.qos);
+
+ /* Reset dongle */
+ node->dongle->reset( &self->idev, 0);
+
+ /* Set to default baudrate */
+ node->dongle->change_speed( &self->idev, 9600);
+}
+
+/*
+ * Function irtty_ioctl (tty, file, cmd, arg)
+ *
+ * The Swiss army knife of system calls :-)
+ *
+ */
+static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd,
+ void *arg)
+{
+ struct irtty_cb *self;
+ int err = 0;
+ int size = _IOC_SIZE(cmd);
+
+ self = (struct irtty_cb *) tty->disc_data;
+
+ ASSERT( self != NULL, return -ENODEV;);
+ ASSERT( self->magic == IRTTY_MAGIC, return -EBADR;);
+
+ if ( _IOC_DIR(cmd) & _IOC_READ)
+ err = verify_area( VERIFY_WRITE, (void *) arg, size);
+ else if ( _IOC_DIR(cmd) & _IOC_WRITE)
+ err = verify_area( VERIFY_READ, (void *) arg, size);
+ if ( err)
+ return err;
+
+ switch(cmd) {
+ case TCGETS:
+ case TCGETA:
+ return n_tty_ioctl( tty, (struct file *) file, cmd,
+ (unsigned long) arg);
+ break;
+ case IRTTY_IOCTDONGLE:
+ /* Initialize dongle */
+ irtty_init_dongle( self, (int) arg);
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+/*
+ * Function irtty_receive_buf( tty, cp, count)
+ *
+ * Handle the 'receiver data ready' interrupt. This function is called
+ * by the 'tty_io' module in the kernel when a block of IrDA data has
+ * been received, which can now be decapsulated and delivered for
+ * further processing
+ */
+static void irtty_receive_buf( struct tty_struct *tty, const unsigned
+ char *cp, char *fp, int count)
+{
+ struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ /* Read the characters out of the buffer */
+ while (count--) {
+ /*
+ * Characters received with a parity error, etc?
+ */
+ if (fp && *fp++) {
+ DEBUG( 0, "Framing or parity error!\n");
+ irda_device_set_media_busy( &self->idev, TRUE);
+ /* sl->rx_errors++; */
+ cp++;
+ continue;
+ }
+ /*
+ * Unwrap and destuff one byte
+ */
+ async_unwrap_char( &self->idev, *cp++);
+ /* self->rx_over_errors++; */
+ }
+}
+
+/*
+ * Function irtty_hard_xmit (skb, dev)
+ *
+ * Transmit skb
+ *
+ */
+static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+ struct irtty_cb *self;
+ struct irda_device *idev;
+ int actual = 0;
+
+ ASSERT( dev != NULL, return 0;);
+ ASSERT( skb != NULL, return 0;);
+
+ if ( dev->tbusy) {
+ DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+
+ return -EBUSY;
+ }
+
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ self = (struct irtty_cb *) idev->priv;
+
+ ASSERT( self != NULL, return 0;);
+ ASSERT( self->magic == IRTTY_MAGIC, return 0;);
+
+ /* Lock transmit buffer */
+ if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ return 0;
+
+ /*
+ * Transfer skb to tx_buff while wrapping, stuffing and making CRC
+ */
+ idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data,
+ idev->tx_buff.truesize);
+
+ self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+
+ dev->trans_start = jiffies;
+
+ if ( self->tty->driver.write)
+ actual = self->tty->driver.write( self->tty, 0,
+ idev->tx_buff.data,
+ idev->tx_buff.len);
+
+ idev->tx_buff.offset = actual;
+ idev->tx_buff.head = idev->tx_buff.data + actual;
+#if 0
+ /*
+ * Did we transmit the whole frame? Commented out for now since
+ * I must check if this optimalization really works. DB.
+ */
+ if (( idev->tx.count - idev->tx.ptr) <= 0) {
+ DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
+ self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ irda_unlock( &self->tbusy);
+ }
+#endif
+
+ dev_kfree_skb( skb);
+
+ return 0;
+}
+
+/*
+ * Function irtty_receive_room (tty)
+ *
+ * Used by the TTY to find out how much data we can receive at a time
+ *
+*/
+static int irtty_receive_room( struct tty_struct *tty)
+{
+ return 65536; /* We can handle an infinite amount of data. :-) */
+}
+
+/*
+ * Function irtty_write_wakeup (tty)
+ *
+ * Called by the driver when there's room for more data. If we have
+ * more packets to send, we send them here.
+ *
+ */
+static void irtty_write_wakeup( struct tty_struct *tty)
+{
+ int actual = 0, count;
+ struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+ struct irda_device *idev;
+
+ /*
+ * First make sure we're connected.
+ */
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ idev = &self->idev;
+
+ /*
+ * Finished with frame?
+ */
+ if ( idev->tx_buff.offset == idev->tx_buff.len) {
+
+ /*
+ * Now serial buffer is almost free & we can start
+ * transmission of another packet
+ */
+ DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+
+ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->stats.tx_packets++;
+ idev->stats.tx_bytes += idev->tx_buff.len;
+
+ /* Tell network layer that we want more frames */
+ mark_bh( NET_BH);
+
+ return;
+ }
+ /*
+ * Write data left in transmit buffer
+ */
+ count = idev->tx_buff.len - idev->tx_buff.offset;
+ actual = tty->driver.write( tty, 0, idev->tx_buff.head, count);
+ idev->tx_buff.offset += actual;
+ idev->tx_buff.head += actual;
+
+ DEBUG( 4, "actual=%d, sent %d\n", actual, count);
+}
+
+/*
+ * Function irtty_is_receiving (idev)
+ *
+ * Return TRUE is we are currently receiving a frame
+ *
+ */
+static int irtty_is_receiving( struct irda_device *idev)
+{
+ return ( idev->rx_buff.state != OUTSIDE_FRAME);
+}
+
+/*
+ * Function irtty_change_speed_ready (idev)
+ *
+ * Are we completely finished with transmitting frames so its possible
+ * to change the speed of the serial port. Warning this function must
+ * be called with a process context!
+ */
+static void irtty_wait_until_sent( struct irda_device *idev)
+{
+ struct irtty_cb *self = (struct irtty_cb *) idev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ DEBUG( 4, "Chars in buffer %d\n",
+ self->tty->driver.chars_in_buffer( self->tty));
+
+ tty_wait_until_sent( self->tty, 0);
+}
+
+int irtty_register_dongle( struct dongle *dongle)
+{
+ struct dongle_q *new;
+
+ /* Check if this compressor has been registred before */
+ if ( hashbin_find ( dongles, dongle->type, NULL)) {
+ DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n");
+ return 0;
+ }
+
+ /* Make new IrDA dongle */
+ new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q),
+ GFP_KERNEL);
+ if (new == NULL) {
+ return 1;
+
+ }
+ memset( new, 0, sizeof( struct dongle_q));
+ new->dongle = dongle;
+
+ /* Insert IrDA compressor into hashbin */
+ hashbin_insert( dongles, (QUEUE *) new, dongle->type, NULL);
+
+ return 0;
+}
+
+void irtty_unregister_dongle( struct dongle *dongle)
+{
+ struct dongle_q *node;
+
+ node = hashbin_remove( dongles, dongle->type, NULL);
+ if ( !node) {
+ DEBUG( 0, __FUNCTION__ "(), dongle not found!\n");
+ return;
+ }
+ kfree( node);
+}
+
+static int irtty_net_init( struct device *dev)
+{
+ /* Set up to be a normal IrDA network device driver */
+ irda_device_setup( dev);
+
+ /* Insert overrides below this line! */
+
+ return 0;
+}
+
+
+static int irtty_net_open( struct device *dev)
+{
+ ASSERT( dev != NULL, return -1;);
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+static int irtty_net_close(struct device *dev)
+{
+ ASSERT( dev != NULL, return -1;);
+
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize IrTTY module
+ *
+ */
+int init_module(void)
+{
+ irtty_init();
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup IrTTY module
+ *
+ */
+void cleanup_module(void)
+{
+ irtty_cleanup();
+}
+
+#endif /* MODULE */
+
+
+
+
+
+
+
diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c
new file mode 100644
index 000000000..faf9eea33
--- /dev/null
+++ b/drivers/net/irda/pc87108.c
@@ -0,0 +1,1502 @@
+/*********************************************************************
+ *
+ * Filename: pc87108.c
+ * Version: 0.8
+ * Description: FIR/MIR driver for the NS PC87108 chip
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sat Nov 7 21:43:15 1998
+ * Modified at: Mon Dec 28 08:46:16 1998
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ * Copyright (c) 1998 Actisys Corp., www.actisys.com
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * Notice that all functions that needs to access the chip in _any_
+ * way, must save BSR register on entry, and restore it on exit.
+ * It is _very_ important to follow this policy!
+ *
+ * __u8 bank;
+ *
+ * bank = inb( iobase+BSR);
+ *
+ * do_your_stuff_here();
+ *
+ * outb( bank, iobase+BSR);
+ *
+ * If you find bugs in this file, its very likely that the same bug
+ * will also be in w83977af_ir.c since the implementations is quite
+ * similar.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/pc87108.h>
+
+#define BROKEN_DONGLE_ID
+
+static char *driver_name = "pc87108";
+
+#define CHIP_IO_EXTENT 8
+
+static unsigned int io[] = { 0x2f8, ~0, ~0, ~0 };
+static unsigned int io2[] = { 0x150, 0, 0, 0};
+static unsigned int irq[] = { 3, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0 };
+
+static struct pc87108 *dev_self[] = { NULL, NULL, NULL, NULL};
+
+static char *dongle_types[] = {
+ "Differential serial interface",
+ "Differential serial interface",
+ "Reserved",
+ "Reserved",
+ "Sharp RY5HD01",
+ "Reserved",
+ "Single-ended serial interface",
+ "Consumer-IR only",
+ "HP HSDL-2300, HP HSDL-3600/HSDL-3610",
+ "IBM31T1100 or Temic TFDS6000/TFDS6500",
+ "Reserved",
+ "Reserved",
+ "HP HSDL-1100/HSDL-2100",
+ "HP HSDL-1100/HSDL-2100"
+ "Supports SIR Mode only",
+ "No dongle connected",
+};
+
+/* Some prototypes */
+static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
+ unsigned int irq, unsigned int dma);
+static int pc87108_close( struct irda_device *idev);
+static int pc87108_probe( int iobase, int board_addr, int irq, int dma);
+static void pc87108_pio_receive( struct irda_device *idev);
+static int pc87108_dma_receive( struct irda_device *idev);
+static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
+static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev);
+static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
+static void pc87108_dma_write( struct irda_device *idev, int iobase);
+static void pc87108_change_speed( struct irda_device *idev, int baud);
+static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void pc87108_wait_until_sent( struct irda_device *idev);
+static int pc87108_is_receiving( struct irda_device *idev);
+static int pc87108_read_dongle_id ( int iobase);
+static void pc87108_init_dongle_interface ( int iobase, int dongle_id);
+
+static int pc87108_net_init( struct device *dev);
+static int pc87108_net_open( struct device *dev);
+static int pc87108_net_close( struct device *dev);
+
+/*
+ * Function pc87108_init ()
+ *
+ * Initialize chip. Just try to find out how many chips we are dealing with
+ * and where they are
+ */
+__initfunc(int pc87108_init(void))
+{
+ int i;
+
+ for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+ int ioaddr = io[i];
+ if (check_region(ioaddr, CHIP_IO_EXTENT))
+ continue;
+ if (pc87108_open( i, io[i], io2[i], irq[i], dma[i]) == 0)
+ return 0;
+ }
+ return -ENODEV;
+}
+
+/*
+ * Function pc87108_cleanup ()
+ *
+ * Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void pc87108_cleanup(void)
+{
+ int i;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ for ( i=0; i < 4; i++) {
+ if ( dev_self[i])
+ pc87108_close( &(dev_self[i]->idev));
+ }
+}
+#endif /* MODULE */
+
+/*
+ * Function pc87108_open (iobase, irq)
+ *
+ * Open driver instance
+ *
+ */
+static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
+ unsigned int irq, unsigned int dma)
+{
+ struct pc87108 *self;
+ struct irda_device *idev;
+ int ret;
+ int dongle_id;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ if (( dongle_id = pc87108_probe( iobase, board_addr, irq, dma)) == -1)
+ return -1;
+
+ /*
+ * Allocate new instance of the driver
+ */
+ self = kmalloc( sizeof(struct pc87108), GFP_KERNEL);
+ if ( self == NULL) {
+ printk( KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+ return -ENOMEM;
+ }
+ memset( self, 0, sizeof(struct pc87108));
+
+ /* Need to store self somewhere */
+ dev_self[i] = self;
+
+ idev = &self->idev;
+
+ /* Initialize IO */
+ idev->io.iobase = iobase;
+ idev->io.irq = irq;
+ idev->io.io_ext = CHIP_IO_EXTENT;
+ idev->io.dma = dma;
+ idev->io.fifo_size = 32;
+
+ /* Lock the port that we need */
+ ret = check_region( idev->io.iobase, idev->io.io_ext);
+ if ( ret < 0) {
+ DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ idev->io.iobase);
+ /* pc87108_cleanup( self->idev); */
+ return -ENODEV;
+ }
+ request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies( &idev->qos);
+
+ /* The only value we must override it the baudrate */
+ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+
+ idev->qos.min_turn_time.bits = 0x07;
+ irda_qos_bits_to_value( &idev->qos);
+
+ /* Specify which buffer allocation policy we need */
+ idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+ idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+ idev->rx_buff.truesize = 14384;
+ idev->tx_buff.truesize = 4000;
+
+ /* Initialize callbacks */
+ idev->hard_xmit = pc87108_hard_xmit;
+ idev->change_speed = pc87108_change_speed;
+ idev->wait_until_sent = pc87108_wait_until_sent;
+ idev->is_receiving = pc87108_is_receiving;
+
+ /* Override the network functions we need to use */
+ idev->netdev.init = pc87108_net_init;
+ idev->netdev.hard_start_xmit = pc87108_hard_xmit;
+ idev->netdev.open = pc87108_net_open;
+ idev->netdev.stop = pc87108_net_close;
+
+ idev->io.dongle_id = dongle_id;
+ pc87108_init_dongle_interface( iobase, dongle_id);
+
+ /* Open the IrDA device */
+ irda_device_open( idev, driver_name, self);
+
+ return 0;
+}
+
+/*
+ * Function pc87108_close (idev)
+ *
+ * Close driver instance
+ *
+ */
+static int pc87108_close( struct irda_device *idev)
+{
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ iobase = idev->io.iobase;
+
+ /* Release the PORT that this driver is using */
+ DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n",
+ idev->io.iobase);
+ release_region( idev->io.iobase, idev->io.io_ext);
+
+ irda_device_close( idev);
+
+ return 0;
+}
+
+/*
+ * Function pc87108_probe (iobase, board_addr, irq, dma)
+ *
+ * Returns non-negative on success.
+ *
+ */
+static int pc87108_probe( int iobase, int board_addr, int irq, int dma)
+{
+ int version;
+ __u8 temp=0;
+ int dongle_id;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Base Address and Interrupt Control Register BAIC */
+ outb(0, board_addr);
+ switch ( iobase) {
+ case 0x3E8: outb( 0x14, board_addr+1); break;
+ case 0x2E8: outb( 0x15, board_addr+1); break;
+ case 0x3F8: outb( 0x16, board_addr+1); break;
+ case 0x2F8: outb( 0x17, board_addr+1); break;
+ default: DEBUG(0, __FUNCTION__ "(), invalid base_address");
+ }
+
+ /* Control Signal Routing Register CSRT */
+ switch (irq) {
+ case 3: temp = 0x01; break;
+ case 4: temp = 0x02; break;
+ case 5: temp = 0x03; break;
+ case 7: temp = 0x04; break;
+ case 9: temp = 0x05; break;
+ case 11: temp = 0x06; break;
+ case 15: temp = 0x07; break;
+ default: DEBUG( 0, __FUNCTION__ "(), invalid irq");
+ }
+ outb( 1, board_addr);
+
+ switch (dma) {
+ case 0: outb( 0x08+temp, board_addr+1); break;
+ case 1: outb( 0x10+temp, board_addr+1); break;
+ case 3: outb( 0x18+temp, board_addr+1); break;
+ default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
+ }
+
+ /* Mode Control Register MCTL */
+ outb( 2, board_addr);
+ outb( 0x03, board_addr+1);
+
+ /* read the Module ID */
+ switch_bank( iobase, BANK3);
+ version = inb( iobase+MID);
+
+ /* should be 0x2? */
+ if (0x20 != (version & 0xf0))
+ {
+ DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+ return -1;
+ }
+
+ /* Switch to advanced mode */
+ switch_bank( iobase, BANK2);
+ outb( ECR1_EXT_SL, iobase+ECR1);
+ switch_bank( iobase, BANK0);
+
+ dongle_id = pc87108_read_dongle_id( iobase);
+ DEBUG( 0, __FUNCTION__ "(), Found dongle: %s\n",
+ dongle_types[ dongle_id]);
+
+ /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
+ switch_bank( iobase, BANK0);
+ outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+
+ /* Set FIFO size to 32 */
+ switch_bank( iobase, BANK2);
+ outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+ /* IRCR2: FEND_MD is set */
+ switch_bank( iobase, BANK5);
+ outb( 0x2a, iobase+4);
+
+ /* Make sure that some defaults are OK */
+ switch_bank( iobase, BANK6);
+ outb( 0x20, iobase+0); /* Set 32 bits FIR CRC */
+ outb( 0x0a, iobase+1); /* Set MIR pulse width */
+ outb( 0x0d, iobase+2); /* Set SIR pulse width */
+ outb( 0x2a, iobase+4); /* Set beginning frag, and preamble length */
+
+ /* Receiver frame length */
+ switch_bank( iobase, BANK4);
+ outb( 2048 & 0xff, iobase+6);
+ outb(( 2048 >> 8) & 0x1f, iobase+7);
+
+ /* Transmitter frame length */
+ outb( 2048 & 0xff, iobase+4);
+ outb(( 2048 >> 8) & 0x1f, iobase+5);
+
+ DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version);
+
+ /* Enable receive interrupts */
+ switch_bank( iobase, BANK0);
+ outb( IER_RXHDL_IE, iobase+IER);
+
+ return dongle_id;
+}
+
+/*
+ * Function pc87108_read_dongle_id (void)
+ *
+ * Try to read dongle indentification. This procedure needs to be executed
+ * once after power-on/reset. It also needs to be used whenever you suspect
+ * that the user may have plugged/unplugged the IrDA Dongle.
+ *
+ */
+static int pc87108_read_dongle_id ( int iobase)
+{
+ int dongle_id;
+ __u8 bank;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ bank = inb( iobase+BSR);
+
+ /* Select Bank 7 */
+ switch_bank( iobase, BANK7);
+
+ /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
+ outb( 0x00, iobase+7);
+
+ /* ID0, 1, and 2 are pulled up/down very slowly */
+ udelay(50);
+
+ /* IRCFG1: read the ID bits */
+ dongle_id = inb( iobase+4) & 0x0f;
+
+#ifdef BROKEN_DONGLE_ID
+ if ( dongle_id == 0x0a)
+ dongle_id = 0x09;
+#endif
+
+ /* Go back to bank 0 before returning */
+ switch_bank( iobase, BANK0);
+
+ DEBUG( 0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
+
+ outb( bank, iobase+BSR);
+
+ return dongle_id;
+}
+
+/*
+ * Function pc87108_init_dongle_interface (iobase, dongle_id)
+ *
+ * This function initializes the dongle for the transceiver that is
+ * used. This procedure needs to be executed once after
+ * power-on/reset. It also needs to be used whenever you suspect that
+ * the dongle is changed.
+ */
+static void pc87108_init_dongle_interface ( int iobase, int dongle_id)
+{
+ int bank;
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* Select Bank 7 */
+ switch_bank( iobase, BANK7);
+
+ /* IRCFG4: set according to dongle_id */
+ switch (dongle_id) {
+ case 0x00: /* same as */
+ case 0x01: /* Differential serial interface */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x02: /* same as */
+ case 0x03: /* Reserved */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x04: /* Sharp RY5HD01 */
+ DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x05: /* Reserved */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet",
+ dongle_types[dongle_id]);
+ break;
+ case 0x06: /* Single-ended serial interface */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x07: /* Consumer-IR only */
+ DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+ DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+ outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */
+ break;
+ case 0x0A: /* same as */
+ case 0x0B: /* Reserved */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x0C: /* same as */
+ case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+ /*
+ * Set irsl0 as input, irsl[1-2] as output, and separate
+ * inputs are used for SIR and MIR/FIR
+ */
+ outb( 0x48, iobase+7);
+ break;
+ case 0x0E: /* Supports SIR Mode only */
+ outb( 0x28, iobase+7); /* Set irsl[0-2] as output */
+ break;
+ case 0x0F: /* No dongle connected */
+ DEBUG( 0, __FUNCTION__ "(), %s\n",
+ dongle_types[dongle_id]);
+ DEBUG( 0, "***\n");
+
+ switch_bank( iobase, BANK0);
+ outb( 0x62, iobase+MCR);
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
+ }
+
+ /* IRCFG1: IRSL1 and 2 are set to IrDA mode */
+ outb( 0x00, iobase+4);
+
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+} /* set_up_dongle_interface */
+
+/*
+ * Function pc87108_change_dongle_speed (iobase, speed, dongle_id)
+ *
+ * Change speed of the attach dongle
+ *
+ */
+static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id)
+{
+ unsigned long flags;
+ __u8 bank;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* Select Bank 7 */
+ switch_bank( iobase, BANK7);
+
+ /* IRCFG1: set according to dongle_id */
+ switch (dongle_id) {
+ case 0x00: /* same as */
+ case 0x01: /* Differential serial interface */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x02: /* same as */
+ case 0x03: /* Reserved */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x04: /* Sharp RY5HD01 */
+ DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ dongle_types[dongle_id]);
+ case 0x05: /* Reserved */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x06: /* Single-ended serial interface */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x07: /* Consumer-IR only */
+ DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+ DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ dongle_types[dongle_id]);
+ case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+ switch_bank( iobase, BANK7);
+ outb_p( 0x01, iobase+4);
+
+ if ( speed == 4000000) {
+ save_flags(flags);
+ cli();
+ outb( 0x81, iobase+4);
+ outb( 0x80, iobase+4);
+ restore_flags(flags);
+ }
+ else
+ outb_p( 0x00, iobase+4);
+ break;
+ case 0x0A: /* same as */
+ case 0x0B: /* Reserved */
+ DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x0C: /* same as */
+ case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+ break;
+ case 0x0E: /* Supports SIR Mode only */
+ break;
+ case 0x0F: /* No dongle connected */
+ DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ dongle_types[dongle_id]);
+
+ switch_bank( iobase, BANK0);
+ outb( 0x62, iobase+MCR);
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n");
+ }
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+}
+
+/*
+ * Function pc87108_change_speed (idev, baud)
+ *
+ * Change the speed of the device
+ *
+ */
+static void pc87108_change_speed( struct irda_device *idev, int speed)
+{
+ __u8 mcr = MCR_SIR;
+ __u8 bank;
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ iobase = idev->io.iobase;
+
+ /* Update accounting for new speed */
+ idev->io.baudrate = speed;
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* Disable interrupts */
+ switch_bank( iobase, BANK0);
+ outb( 0, iobase+IER);
+
+ /* Select Bank 2 */
+ switch_bank( iobase, BANK2);
+
+ outb( 0x00, iobase+BGDH);
+ switch ( speed) {
+ case 9600: outb( 0x0c, iobase+BGDL); break;
+ case 19200: outb( 0x06, iobase+BGDL); break;
+ case 37600: outb( 0x03, iobase+BGDL); break;
+ case 57600: outb( 0x02, iobase+BGDL); break;
+ case 115200: outb( 0x01, iobase+BGDL); break;
+ case 576000:
+ switch_bank( iobase, BANK5);
+
+ /* IRCR2: MDRS is set */
+ outb( inb( iobase+4) | 0x04, iobase+4);
+
+ mcr = MCR_MIR;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ break;
+ case 1152000:
+ mcr = MCR_MIR;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ break;
+ case 4000000:
+ mcr = MCR_FIR;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ break;
+ default:
+ mcr = MCR_FIR;
+ DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+ break;
+ }
+
+ /* Set appropriate speed mode */
+ switch_bank(iobase, BANK0);
+ outb( mcr|MCR_TX_DFR, iobase+MCR);
+
+ /* Give some hits to the transceiver */
+ pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id);
+
+ /* Set FIFO threshold to TX17, RX16 */
+ switch_bank( iobase, BANK0);
+ outb( FCR_RXTH| /* Set Rx FIFO threshold */
+ FCR_TXTH| /* Set Tx FIFO threshold */
+ FCR_TXSR| /* Reset Tx FIFO */
+ FCR_RXSR| /* Reset Rx FIFO */
+ FCR_FIFO_EN, /* Enable FIFOs */
+ iobase+FCR);
+ /* outb( 0xa7, iobase+FCR); */
+
+ /* Set FIFO size to 32 */
+ switch_bank( iobase, BANK2);
+ outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+ idev->netdev.tbusy = 0;
+
+ /* Enable some interrupts so we can receive frames */
+ switch_bank( iobase, BANK0);
+ if ( speed > 115200) {
+ outb( IER_SFIF_IE, iobase+IER);
+ pc87108_dma_receive( idev);
+ } else
+ outb( IER_RXHDL_IE, iobase+IER);
+
+ /* Restore BSR */
+ outb( bank, iobase+BSR);
+}
+
+/*
+ * Function pc87108_hard_xmit (skb, dev)
+ *
+ * Transmit the frame!
+ *
+ */
+static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ __u8 bank;
+ int mtt;
+
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+
+ if ( dev->tbusy) {
+ DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+
+ return -EBUSY;
+ }
+
+ /* Lock transmit buffer */
+ if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* Decide if we should use PIO or DMA transfer */
+ if ( idev->io.baudrate > 115200) {
+ memcpy( idev->tx_buff.data, skb->data, skb->len);
+ idev->tx_buff.len = skb->len;
+ idev->tx_buff.head = idev->tx_buff.data;
+ idev->tx_buff.offset = 0;
+
+ mtt = irda_get_mtt( skb);
+ if ( mtt > 50) {
+ /* Adjust for timer resolution */
+ mtt = mtt / 125 + 1;
+
+ /* Setup timer */
+ switch_bank( iobase, BANK4);
+ outb( mtt & 0xff, iobase+TMRL);
+ outb(( mtt >> 8) & 0x0f, iobase+TMRH);
+
+ /* Start timer */
+ outb( IRCR1_TMR_EN, iobase+IRCR1);
+ idev->io.direction = IO_XMIT;
+
+ /* Enable timer interrupt */
+ switch_bank( iobase, BANK0);
+ outb( IER_TMR_IE, iobase+IER);
+ } else {
+ /* Use udelay for delays less than 50 us. */
+ if (mtt)
+ udelay( mtt);
+
+ /* Enable DMA interrupt */
+ switch_bank( iobase, BANK0);
+ outb( IER_DMA_IE, iobase+IER);
+ pc87108_dma_write( idev, iobase);
+ }
+ } else {
+ idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data,
+ idev->tx_buff.truesize);
+
+ idev->tx_buff.offset = 0;
+ idev->tx_buff.head = idev->tx_buff.data;
+
+ /* Add interrupt on tx low level (will fire immediately) */
+ switch_bank( iobase, BANK0);
+ outb( IER_TXLDL_IE, iobase+IER);
+ }
+ dev_kfree_skb( skb);
+
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+ return 0;
+}
+
+/*
+ * Function pc87108_dma_xmit (idev, iobase)
+ *
+ * Transmit data using DMA
+ *
+ */
+static void pc87108_dma_write( struct irda_device *idev, int iobase)
+{
+ int bsr;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Save current bank */
+ bsr = inb( iobase+BSR);
+
+ /* Disable DMA */
+ switch_bank(iobase, BANK0);
+ outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+ setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len,
+ DMA_MODE_WRITE);
+
+ /* idev->media_busy = TRUE; */
+ idev->io.direction = IO_XMIT;
+
+ /* Choose transmit DMA channel */
+ switch_bank(iobase, BANK2);
+ outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL,
+ iobase+ECR1);
+
+ /* Enable DMA */
+ switch_bank( iobase, BANK0);
+ outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+ /* Restore bank register */
+ outb( bsr, iobase+BSR);
+}
+
+/*
+ * Function pc87108_pio_xmit (idev, iobase)
+ *
+ * Transmit data using PIO. Returns the number of bytes that actually
+ * got transfered
+ *
+ */
+static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size)
+{
+ int actual = 0;
+ __u8 bank;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ switch_bank( iobase, BANK0);
+ if (!(inb_p( iobase+LSR) & LSR_TXEMP)) {
+ DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+
+ fifo_size -= 17;
+ DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+ }
+
+ /* Fill FIFO with current frame */
+ while (( fifo_size-- > 0) && (actual < len)) {
+ /* Transmit next byte */
+ outb( buf[actual++], iobase+TXD);
+ }
+
+ DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ fifo_size, actual, len);
+
+ /* Restore bank */
+ outb( bank, iobase+BSR);
+
+ return actual;
+}
+
+/*
+ * Function pc87108_dma_xmit_complete (idev)
+ *
+ * The transfer of a frame in finished. This function will only be called
+ * by the interrupt handler
+ *
+ */
+static void pc87108_dma_xmit_complete( struct irda_device *idev)
+{
+ int iobase;
+ __u8 bank;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ iobase = idev->io.iobase;
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* Disable DMA */
+ switch_bank( iobase, BANK0);
+ outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+ /* Check for underrrun! */
+ if ( inb( iobase+ASCR) & ASCR_TXUR) {
+ idev->stats.tx_errors++;
+ idev->stats.tx_fifo_errors++;
+
+ /* Clear bit, by writing 1 into it */
+ outb( ASCR_TXUR, iobase+ASCR);
+ } else {
+ idev->stats.tx_packets++;
+ idev->stats.tx_bytes += idev->tx_buff.len;
+ }
+
+ /* Unlock tx_buff and request another frame */
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->media_busy = FALSE;
+
+ /* Tell the network layer, that we can accept more frames */
+ mark_bh( NET_BH);
+
+ /* Restore bank */
+ outb( bank, iobase+BSR);
+}
+
+/*
+ * Function pc87108_dma_receive (idev)
+ *
+ * Get ready for receiving a frame. The device will initiate a DMA
+ * if it starts to receive a frame.
+ *
+ */
+static int pc87108_dma_receive( struct irda_device *idev)
+{
+ struct pc87108 *self;
+ int iobase;
+ __u8 bsr;
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ DEBUG( 4, __FUNCTION__ "\n");
+
+ self = idev->priv;
+ iobase= idev->io.iobase;
+
+ /* Save current bank */
+ bsr = inb( iobase+BSR);
+
+ /* Disable DMA */
+ switch_bank( iobase, BANK0);
+ outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+ setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize,
+ DMA_MODE_READ);
+
+ /* driver->media_busy = FALSE; */
+ idev->io.direction = IO_RECV;
+ idev->rx_buff.head = idev->rx_buff.data;
+ idev->rx_buff.offset = 0;
+
+ /* Reset Rx FIFO. This will also flush the ST_FIFO */
+ outb( FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+ self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
+
+ /* Choose DMA Rx, DMA Fairness, and Advanced mode */
+ switch_bank(iobase, BANK2);
+ outb(( inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL,
+ iobase+ECR1);
+
+ /* enable DMA */
+ switch_bank(iobase, BANK0);
+ outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+ /* Restore bank register */
+ outb( bsr, iobase+BSR);
+
+ DEBUG( 4, __FUNCTION__ "(), done!\n");
+
+ return 0;
+}
+
+/*
+ * Function pc87108_dma_receive_complete (idev)
+ *
+ * Finished with receiving frames
+ *
+ *
+ */
+static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase)
+{
+ struct sk_buff *skb;
+ struct pc87108 *self;
+ struct st_fifo *st_fifo;
+ int len;
+ __u8 bank;
+ __u8 status;
+
+ self = idev->priv;
+ st_fifo = &self->st_fifo;
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ iobase = idev->io.iobase;
+
+ /* Read status FIFO */
+ switch_bank(iobase, BANK5);
+ while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
+ st_fifo->entries[ st_fifo->tail].status = status;
+
+ st_fifo->entries[ st_fifo->tail].len = inb(iobase+RFLFL);
+ st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+
+ st_fifo->tail++;
+ st_fifo->len++;
+ }
+
+ /* Try to process all entries in status FIFO */
+ switch_bank( iobase, BANK0);
+ while ( st_fifo->len) {
+
+ /* Get first entry */
+ status = st_fifo->entries[ st_fifo->head].status;
+ len = st_fifo->entries[ st_fifo->head].len;
+ st_fifo->head++;
+ st_fifo->len--;
+
+ /* Check for errors */
+ if ( status & FRM_ST_ERR_MSK) {
+ if ( status & FRM_ST_LOST_FR) {
+ /* Add number of lost frames to stats */
+ idev->stats.rx_errors += len;
+ } else {
+ /* Skip frame */
+ idev->stats.rx_errors++;
+
+ idev->rx_buff.offset += len;
+ idev->rx_buff.head += len;
+
+ if ( status & FRM_ST_MAX_LEN)
+ idev->stats.rx_length_errors++;
+
+ if ( status & FRM_ST_PHY_ERR)
+ idev->stats.rx_frame_errors++;
+
+ if ( status & FRM_ST_BAD_CRC)
+ idev->stats.rx_crc_errors++;
+ }
+ /* The errors below can be reported in both cases */
+ if ( status & FRM_ST_OVR1)
+ idev->stats.rx_fifo_errors++;
+
+ if ( status & FRM_ST_OVR2)
+ idev->stats.rx_fifo_errors++;
+
+ } else {
+ /* Check if we have transfered all data to memory */
+ if ( inb( iobase+LSR) & LSR_RXDA) {
+ /* Put this entry back in fifo */
+ st_fifo->head--;
+ st_fifo->len++;
+ st_fifo->entries[st_fifo->head].status = status;
+ st_fifo->entries[ st_fifo->head].len = len;
+
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+ return FALSE; /* I'll be back! */
+ }
+
+ /* Should be OK then */
+ skb = dev_alloc_skb( len+1);
+ if (skb == NULL) {
+ printk( KERN_INFO __FUNCTION__
+ "(), memory squeeze, dropping frame.\n");
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+ return FALSE;
+ }
+
+ /* Make sure IP header gets aligned */
+ skb_reserve( skb, 1);
+
+ /* Copy frame without CRC */
+ if ( idev->io.baudrate < 4000000) {
+ skb_put( skb, len-2);
+ memcpy( skb->data, idev->rx_buff.head, len-2);
+ } else {
+ skb_put( skb, len-4);
+ memcpy( skb->data, idev->rx_buff.head, len-4);
+ }
+
+ /* Move to next frame */
+ idev->rx_buff.offset += len;
+ idev->rx_buff.head += len;
+ idev->stats.rx_packets++;
+
+ skb->dev = &idev->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx( skb);
+ }
+ }
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+ return TRUE;
+}
+
+/*
+ * Function pc87108_pio_receive (idev)
+ *
+ * Receive all data in receiver FIFO
+ *
+ */
+static void pc87108_pio_receive( struct irda_device *idev)
+{
+ __u8 byte = 0x00;
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ iobase = idev->io.iobase;
+
+ if ( idev->rx_buff.len == 0) {
+ idev->rx_buff.head = idev->rx_buff.data;
+ }
+
+ /* Receive all characters in Rx FIFO */
+ do {
+ byte = inb( iobase+RXD);
+ async_unwrap_char( idev, byte);
+
+ } while ( inb( iobase+LSR) & LSR_RXDA); /* Data available */
+}
+
+/*
+ * Function pc87108_sir_interrupt (idev, eir)
+ *
+ * Handle SIR interrupt
+ *
+ */
+static __u8 pc87108_sir_interrupt( struct irda_device *idev, int eir)
+{
+ int len;
+ int actual;
+ __u8 new_ier = 0;
+
+ /* Transmit FIFO low on data */
+ if ( eir & EIR_TXLDL_EV) {
+ /* Write data left in transmit buffer */
+ len = idev->tx_buff.len - idev->tx_buff.offset;
+
+ ASSERT( len > 0, return 0;);
+ actual = pc87108_pio_write( idev->io.iobase,
+ idev->tx_buff.head,
+ len, idev->io.fifo_size);
+ idev->tx_buff.offset += actual;
+ idev->tx_buff.head += actual;
+
+ idev->io.direction = IO_XMIT;
+ ASSERT( actual <= len, return 0;);
+
+ /* Check if finished */
+ if ( actual == len) {
+ DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->stats.tx_packets++;
+
+ mark_bh(NET_BH);
+
+ new_ier |= IER_TXEMP_IE;
+ } else
+ new_ier |= IER_TXLDL_IE;
+ }
+ /* Check if transmission has completed */
+ if ( eir & EIR_TXEMP_EV) {
+
+ /* Turn around and get ready to receive some data */
+ idev->io.direction = IO_RECV;
+ new_ier |= IER_RXHDL_IE;
+ }
+
+ /* Rx FIFO threshold or timeout */
+ if ( eir & EIR_RXHDL_EV) {
+ pc87108_pio_receive( idev);
+
+ /* Keep receiving */
+ new_ier |= IER_RXHDL_IE;
+ }
+ return new_ier;
+}
+
+/*
+ * Function pc87108_fir_interrupt (idev, eir)
+ *
+ * Handle MIR/FIR interrupt
+ *
+ */
+static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
+ int eir)
+{
+ __u8 new_ier = 0;
+ __u8 bank;
+
+ bank = inb( iobase+BSR);
+
+ /* Status event, or end of frame detected in FIFO */
+ if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+ if ( pc87108_dma_receive_complete( idev, iobase)) {
+
+ /* Wait for next status FIFO interrupt */
+ new_ier |= IER_SFIF_IE;
+ } else {
+ /* DMA not finished yet */
+
+ /* Set timer value, resolution 125 us */
+ switch_bank( iobase, BANK4);
+ outb( 0x0f, iobase+TMRL); /* 125 us */
+ outb( 0x00, iobase+TMRH);
+
+ /* Start timer */
+ outb( IRCR1_TMR_EN, iobase+IRCR1);
+
+ new_ier |= IER_TMR_IE;
+ }
+ }
+ /* Timer finished */
+ if ( eir & EIR_TMR_EV) {
+ /* Disable timer */
+ switch_bank( iobase, BANK4);
+ outb( 0, iobase+IRCR1);
+
+ /* Clear timer event */
+ switch_bank(iobase, BANK0);
+ outb( ASCR_CTE, iobase+ASCR);
+
+ /* Check if this is a TX timer interrupt */
+ if ( idev->io.direction == IO_XMIT) {
+ pc87108_dma_write( idev, iobase);
+
+ /* Interrupt on DMA */
+ new_ier |= IER_DMA_IE;
+ } else {
+ /* Check if DMA has now finished */
+ pc87108_dma_receive_complete( idev, iobase);
+
+ new_ier |= IER_SFIF_IE;
+ }
+ }
+ /* Finished with transmission */
+ if ( eir & EIR_DMA_EV) {
+ pc87108_dma_xmit_complete( idev);
+
+ /* Check if there are more frames to be transmitted */
+ if ( irda_device_txqueue_empty( idev)) {
+ /* Prepare for receive */
+ pc87108_dma_receive( idev);
+
+ new_ier = IER_LS_IE|IER_SFIF_IE;
+ }
+ }
+ outb( bank, iobase+BSR);
+
+ return new_ier;
+}
+
+/*
+ * Function pc87108_interrupt (irq, dev_id, regs)
+ *
+ * An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ __u8 bsr, eir, ier;
+ int iobase;
+
+ struct irda_device *idev = (struct irda_device *) dev_id;
+
+ if (idev == NULL) {
+ printk( KERN_WARNING "%s: irq %d for unknown device.\n",
+ driver_name, irq);
+ return;
+ }
+
+ idev->netdev.interrupt = 1;
+
+ iobase = idev->io.iobase;
+
+ /* Save current bank */
+ bsr = inb( iobase+BSR);
+
+ switch_bank( iobase, BANK0);
+ ier = inb( iobase+IER);
+ eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */
+
+ outb( 0, iobase+IER); /* Disable interrupts */
+
+ if ( eir) {
+ /* Dispatch interrupt handler for the current speed */
+ if ( idev->io.baudrate > 115200)
+ ier = pc87108_fir_interrupt( idev, iobase, eir);
+ else
+ ier = pc87108_sir_interrupt( idev, eir);
+ }
+
+ outb( ier, iobase+IER); /* Restore interrupts */
+ outb( bsr, iobase+BSR); /* Restore bank register */
+
+ idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function pc87108_wait_until_sent (idev)
+ *
+ * This function should put the current thread to sleep until all data
+ * have been sent, so it is safe to f.eks. change the speed.
+ */
+static void pc87108_wait_until_sent( struct irda_device *idev)
+{
+ /* Just delay 60 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(6);
+}
+
+/*
+ * Function pc87108_is_receiving (idev)
+ *
+ * Return TRUE is we are currently receiving a frame
+ *
+ */
+static int pc87108_is_receiving( struct irda_device *idev)
+{
+ int status = FALSE;
+ int iobase;
+ __u8 bank;
+
+ ASSERT( idev != NULL, return FALSE;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+ if ( idev->io.baudrate > 115200) {
+ iobase = idev->io.iobase;
+
+ /* Check if rx FIFO is not empty */
+ bank = inb( iobase+BSR);
+ switch_bank( iobase, BANK2);
+ if (( inb( iobase+RXFLV) & 0x3f) != 0) {
+ /* We are receiving something */
+ status = TRUE;
+ }
+ outb( bank, iobase+BSR);
+ } else
+ status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+
+ return status;
+}
+
+/*
+ * Function pc87108_net_init (dev)
+ *
+ * Initialize network device
+ *
+ */
+static int pc87108_net_init( struct device *dev)
+{
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Setup to be a normal IrDA network device driver */
+ irda_device_setup( dev);
+
+ /* Insert overrides below this line! */
+
+ return 0;
+}
+
+
+/*
+ * Function pc87108_net_open (dev)
+ *
+ * Start the device
+ *
+ */
+static int pc87108_net_open( struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ __u8 bank;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name,
+ (void *) idev)) {
+ return -EAGAIN;
+ }
+ /*
+ * Always allocate the DMA channel after the IRQ,
+ * and clean up on failure.
+ */
+ if (request_dma(idev->io.dma, idev->name)) {
+ free_irq( idev->io.irq, idev);
+ return -EAGAIN;
+ }
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* turn on interrupts */
+ switch_bank( iobase, BANK0);
+ outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/*
+ * Function pc87108_net_close (dev)
+ *
+ * Stop the device
+ *
+ */
+static int pc87108_net_close(struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ __u8 bank;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ disable_dma( idev->io.dma);
+
+ /* Save current bank */
+ bank = inb( iobase+BSR);
+
+ /* Disable interrupts */
+ switch_bank( iobase, BANK0);
+ outb( 0, iobase+IER);
+
+ free_irq( idev->io.irq, idev);
+ free_dma( idev->io.dma);
+
+ /* Restore bank register */
+ outb( bank, iobase+BSR);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *
+ *
+ */
+int init_module(void)
+{
+ pc87108_init();
+
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *
+ *
+ */
+void cleanup_module(void)
+{
+ pc87108_cleanup();
+}
+
+#endif
+
diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c
new file mode 100644
index 000000000..bdada4afa
--- /dev/null
+++ b/drivers/net/irda/tekram.c
@@ -0,0 +1,314 @@
+/*********************************************************************
+ *
+ * Filename: tekram.c
+ * Version: 0.4
+ * Description: Implementation of the Tekram IrMate IR-210B dongle
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Wed Oct 21 20:02:35 1998
+ * Modified at: Mon Jan 18 11:30:38 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irtty.h>
+#include <net/irda/dongle.h>
+
+static void tekram_reset( struct irda_device *dev, int unused);
+static void tekram_open( struct irda_device *dev, int type);
+static void tekram_close( struct irda_device *dev);
+static void tekram_change_speed( struct irda_device *dev, int baud);
+static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos);
+
+static struct dongle dongle = {
+ TEKRAM_DONGLE,
+ tekram_open,
+ tekram_close,
+ tekram_reset,
+ tekram_change_speed,
+ tekram_init_qos,
+};
+
+__initfunc(void tekram_init(void))
+{
+ irtty_register_dongle( &dongle);
+}
+
+void tekram_cleanup(void)
+{
+ irtty_unregister_dongle( &dongle);
+}
+
+static void tekram_open( struct irda_device *dev, int type)
+{
+ strcat( dev->name, " <-> tekram");
+
+ MOD_INC_USE_COUNT;
+}
+
+static void tekram_close( struct irda_device *dev)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function tekram_change_speed (tty, baud)
+ *
+ * Set the speed for the Tekram IRMate 210 type dongle. Warning, this
+ * function must be called with a process context!
+ *
+ * Algorithm
+ * 1. clear DTR
+ * 2. set RTS, and wait at least 7 us
+ * 3. send Control Byte to the IR-210 through TXD to set new baud rate
+ * wait until the stop bit of Control Byte is sent (for 9600 baud rate,
+ * it takes about 100 msec)
+ * 5. clear RTS (return to NORMAL Operation)
+ * 6. wait at least 50 us, new setting (baud rate, etc) takes effect here
+ * after
+ */
+static void tekram_change_speed( struct irda_device *dev, int baud)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ struct termios old_termios;
+ int arg = 0;
+ int cflag;
+ __u8 byte;
+ int actual;
+ mm_segment_t fs;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( dev != NULL, return;);
+ ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) dev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ if ( !self->tty)
+ return;
+
+ tty = self->tty;
+
+ old_termios = *(tty->termios);
+ cflag = tty->termios->c_cflag;
+
+ cflag &= ~CBAUD;
+
+ switch (baud) {
+ case 9600:
+ default:
+ cflag |= B9600;
+ byte = 4;
+ break;
+ case 19200:
+ cflag |= B19200;
+ byte = 3;
+ break;
+ case 34800:
+ cflag |= B38400;
+ byte = 2;
+ break;
+ case 57600:
+ cflag |= B57600;
+ byte = 1;
+ break;
+ case 115200:
+ cflag |= B115200;
+ byte = 0;
+ break;
+ }
+
+ /* Set DTR, Clear RTS */
+ DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
+ arg = TIOCM_DTR | TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg)) {
+ DEBUG( 0, "error setting Tekram speed!\n");
+ }
+ set_fs(fs);
+
+ /* Wait at least 7us */
+ udelay( 7);
+
+ DEBUG( 0, __FUNCTION__ "(), Writing control byte\n");
+ /* Write control byte */
+ if ( tty->driver.write)
+ actual = tty->driver.write( self->tty, 0, &byte, 1);
+
+ /* Wait at least 100 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout( 10);
+
+ /* Set DTR, Set RTS */
+ DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n");
+ arg = TIOCM_DTR | TIOCM_RTS | TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg)) {
+ DEBUG( 0, "error setting Tekram speed!\n");
+ }
+ set_fs(fs);
+
+ DEBUG( 0, __FUNCTION__ "(), Setting new speed on serial port\n");
+ /* Now change the speed of the serial port */
+ tty->termios->c_cflag = cflag;
+ tty->driver.set_termios( tty, &old_termios);
+}
+
+/*
+ * Function tekram_reset (driver)
+ *
+ * This function resets the tekram dongle. Warning, this function
+ * must be called with a process context!!
+ *
+ * Algorithm:
+ * 0. set RTS and DTR, and wait 50 ms
+ * ( power off the IR-210 )
+ * 1. clear RTS
+ * 2. set DTR, and wait at least 1 ms
+ * 3. clear DTR to SPACE state, wait at least 50 us for further
+ * operation
+ */
+void tekram_reset( struct irda_device *dev, int unused)
+{
+ struct irtty_cb *self;
+ struct tty_struct *tty;
+ int arg = 0;
+ mm_segment_t fs;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( dev != NULL, return;);
+ ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = (struct irtty_cb *) dev->priv;
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+ tty = self->tty;
+ if ( !tty)
+ return;
+
+ DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
+ arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg))
+ {
+ DEBUG(0, "error setting ESI speed!\n");
+ }
+ set_fs(fs);
+
+ /* Sleep 50 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(5);
+
+ DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n");
+ /* Set DTR, clear RTS */
+ arg = TIOCM_DTR | TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET,
+ (unsigned long) &arg)) {
+ DEBUG( 0, "Error setting Tekram speed!\n");
+ }
+ set_fs(fs);
+
+ /* Should sleep 1 ms, but 10-20 should not do any harm */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(2);
+
+ DEBUG( 0, __FUNCTION__ "(), STATE3\n");
+ /* Clear DTR, clear RTS */
+ arg = TIOCM_OUT2;
+
+ fs = get_fs();
+ set_fs( get_ds());
+
+ if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) {
+ DEBUG( 0, "error setting Tekram speed!\n");
+ }
+ set_fs(fs);
+
+ /* Finished! */
+}
+
+/*
+ * Function tekram_init_qos (qos)
+ *
+ * Initialize QoS capabilities
+ *
+ */
+static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos)
+{
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize Tekram module
+ *
+ */
+int init_module(void)
+{
+ tekram_init();
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Cleanup Tekram module
+ *
+ */
+void cleanup_module(void)
+{
+ tekram_cleanup();
+}
+
+#endif
diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c
new file mode 100644
index 000000000..05da78a00
--- /dev/null
+++ b/drivers/net/irda/uircc.c
@@ -0,0 +1,914 @@
+/*********************************************************************
+ *
+ * Filename: uircc.c
+ * Version: 0.1
+ * Description: Driver for the Sharp Universal Infrared
+ * Communications Controller (UIRCC)
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sat Dec 26 10:59:03 1998
+ * Modified at: Tue Jan 19 23:54:04 1999
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * Applicable Models : Tecra 510CDT, 500C Series, 530CDT, 520CDT,
+ * 740CDT, Portege 300CT, 660CDT, Satellite 220C Series,
+ * Satellite Pro, 440C Series, 470CDT, 460C Series, 480C Series
+ *
+ * Notice that FIR mode is not working yet, since I don't know
+ * how to make the UIRCC drive the interrupt line, and not the
+ * UART (which is used for SIR speeds). Please mail me if you know!
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/uircc.h>
+#include <net/irda/irport.h>
+
+static char *driver_name = "uircc";
+
+#define CHIP_IO_EXTENT 16
+
+static unsigned int io[] = { 0x300, ~0, ~0, ~0 };
+static unsigned int io2[] = { 0x3e8, 0, 0, 0};
+static unsigned int irq[] = { 11, 0, 0, 0 };
+static unsigned int dma[] = { 5, 0, 0, 0 };
+
+static struct uircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+
+/* Some prototypes */
+static int uircc_open( int i, unsigned int iobase, unsigned int board_addr,
+ unsigned int irq, unsigned int dma);
+static int uircc_close( struct irda_device *idev);
+static int uircc_probe( int iobase, int board_addr, int irq, int dma);
+static int uircc_dma_receive( struct irda_device *idev);
+static int uircc_dma_receive_complete(struct irda_device *idev, int iobase);
+static int uircc_hard_xmit( struct sk_buff *skb, struct device *dev);
+static void uircc_dma_write( struct irda_device *idev, int iobase);
+static void uircc_change_speed( struct irda_device *idev, int baud);
+static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void uircc_wait_until_sent( struct irda_device *idev);
+static int uircc_is_receiving( struct irda_device *idev);
+
+static int uircc_net_init( struct device *dev);
+static int uircc_net_open( struct device *dev);
+static int uircc_net_close( struct device *dev);
+
+/*
+ * Function uircc_init ()
+ *
+ * Initialize chip. Just try to find out how many chips we are dealing with
+ * and where they are
+ */
+__initfunc(int uircc_init(void))
+{
+ int i;
+
+ for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+ int ioaddr = io[i];
+ if (check_region(ioaddr, CHIP_IO_EXTENT))
+ continue;
+ if (uircc_open( i, io[i], io2[i], irq[i], dma[i]) == 0)
+ return 0;
+ }
+ return -ENODEV;
+}
+
+/*
+ * Function uircc_cleanup ()
+ *
+ * Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void uircc_cleanup(void)
+{
+ int i;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ for ( i=0; i < 4; i++) {
+ if ( dev_self[i])
+ uircc_close( &(dev_self[i]->idev));
+ }
+}
+#endif /* MODULE */
+
+/*
+ * Function uircc_open (iobase, irq)
+ *
+ * Open driver instance
+ *
+ */
+static int uircc_open( int i, unsigned int iobase, unsigned int iobase2,
+ unsigned int irq, unsigned int dma)
+{
+ struct uircc_cb *self;
+ struct irda_device *idev;
+ int ret;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ if (( uircc_probe( iobase, iobase2, irq, dma)) == -1)
+ return -1;
+
+ /*
+ * Allocate new instance of the driver
+ */
+ self = kmalloc( sizeof(struct uircc_cb), GFP_KERNEL);
+ if ( self == NULL) {
+ printk( KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+ return -ENOMEM;
+ }
+ memset( self, 0, sizeof(struct uircc_cb));
+
+ /* Need to store self somewhere */
+ dev_self[i] = self;
+
+ idev = &self->idev;
+
+ /* Initialize IO */
+ idev->io.iobase = iobase;
+ idev->io.iobase2 = iobase2; /* Used by irport */
+ idev->io.irq = irq;
+ idev->io.io_ext = CHIP_IO_EXTENT;
+ idev->io.io_ext2 = 8; /* Used by irport */
+ idev->io.dma = dma;
+ idev->io.fifo_size = 16;
+
+ /* Lock the port that we need */
+ ret = check_region( idev->io.iobase, idev->io.io_ext);
+ if ( ret < 0) {
+ DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ idev->io.iobase);
+ /* uircc_cleanup( self->idev); */
+ return -ENODEV;
+ }
+ ret = check_region( idev->io.iobase2, idev->io.io_ext2);
+ if ( ret < 0) {
+ DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ idev->io.iobase2);
+ /* uircc_cleanup( self->idev); */
+ return -ENODEV;
+ }
+ request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+ request_region( idev->io.iobase2, idev->io.io_ext2, idev->name);
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies( &idev->qos);
+
+ /* The only value we must override it the baudrate */
+ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+
+ idev->qos.min_turn_time.bits = 0x07;
+ irda_qos_bits_to_value( &idev->qos);
+
+ /* Specify which buffer allocation policy we need */
+ idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+ idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+ idev->rx_buff.truesize = 4000;
+ idev->tx_buff.truesize = 4000;
+
+ /* Initialize callbacks */
+ idev->hard_xmit = uircc_hard_xmit;
+ idev->change_speed = uircc_change_speed;
+ idev->wait_until_sent = uircc_wait_until_sent;
+ idev->is_receiving = uircc_is_receiving;
+
+ /* Override the network functions we need to use */
+ idev->netdev.init = uircc_net_init;
+ idev->netdev.hard_start_xmit = uircc_hard_xmit;
+ idev->netdev.open = uircc_net_open;
+ idev->netdev.stop = uircc_net_close;
+
+ irport_open( iobase2);
+
+ /* Open the IrDA device */
+ irda_device_open( idev, driver_name, self);
+
+ return 0;
+}
+
+/*
+ * Function uircc_close (idev)
+ *
+ * Close driver instance
+ *
+ */
+static int uircc_close( struct irda_device *idev)
+{
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ iobase = idev->io.iobase;
+
+ /* Disable modem */
+ outb( 0x00, iobase+UIRCC_CR10);
+
+ irport_close( idev->io.iobase2);
+
+ /* Release the PORT that this driver is using */
+ DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
+ release_region( idev->io.iobase, idev->io.io_ext);
+
+ if ( idev->io.iobase2) {
+ DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n",
+ idev->io.iobase2);
+ release_region( idev->io.iobase2, idev->io.io_ext2);
+ }
+
+ irda_device_close( idev);
+
+ return 0;
+}
+
+/*
+ * Function uircc_probe (iobase, board_addr, irq, dma)
+ *
+ * Returns non-negative on success.
+ *
+ */
+static int uircc_probe( int iobase, int iobase2, int irq, int dma)
+{
+ int version;
+ int probe_irq=0;
+ unsigned long mask;
+ int i;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ /* read the chip version, should be 0x03 */
+ version = inb( iobase+UIRCC_SR8);
+
+ if ( version != 0x03) {
+ DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+ return -1;
+ }
+ DEBUG( 0, "UIRCC driver loaded. Version: 0x%02x\n", version);
+
+ /* Reset chip */
+ outb( UIRCC_CR0_SYS_RST, iobase+UIRCC_CR0);
+
+ /* Initialize some registers */
+ outb( 0, iobase+UIRCC_CR11);
+ outb( 0, iobase+UIRCC_CR9);
+
+ /* Enable DMA single mode */
+ outb( UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET,
+ iobase+UIRCC_CR1);
+
+ /* Disable interrupts */
+ outb( 0xff, iobase+UIRCC_CR2);
+
+#if 0
+ irport_close( iobase2);
+
+ for (i=0;i<1;i++) {
+
+ /* Set appropriate speed mode */
+ outb( UIRCC_CR10_FIR, iobase+UIRCC_CR10);
+
+ /* Enable DMA single mode */
+ outb( UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET,
+ iobase+UIRCC_CR1);
+
+ /* Set up timer */
+ outb( 0x01, iobase+UIRCC_CR12);
+ outb( 0x00, iobase+UIRCC_CR13);
+
+ /* Set interrupt mask */
+ outb( 0x82, iobase+UIRCC_CR2);
+
+ DEBUG( 0, __FUNCTION__ "(*), sr3=%#x, sr2=%#x, sr10=%#x, sr12=%#x\n",
+ inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2),
+ inb( iobase+UIRCC_SR10), inb( iobase+UIRCC_SR12));
+
+ mask = probe_irq_on();
+
+ /* Enable timer */
+ outb( 0x08, iobase+UIRCC_CR11);
+
+ udelay( 10000); /* Wait for interrupt! */
+
+ probe_irq = probe_irq_off( mask);
+
+ DEBUG( 0, "Found irq=%d\n", probe_irq);
+
+ DEBUG( 0, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x, sr12=%#x\n",
+ inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2),
+ inb( iobase+UIRCC_SR10), inb( iobase+UIRCC_SR12));
+
+
+ /* Diable timer */
+ outb( 0x00, iobase+UIRCC_CR11);
+ }
+#endif
+
+ /* Set self poll address */
+
+ return 0;
+}
+
+/*
+ * Function uircc_change_speed (idev, baud)
+ *
+ * Change the speed of the device
+ *
+ */
+static void uircc_change_speed( struct irda_device *idev, int speed)
+{
+ struct uircc_cb *self;
+ int iobase;
+ int modem = UIRCC_CR10_SIR;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = idev->priv;
+ iobase = idev->io.iobase;
+
+ /* Update accounting for new speed */
+ idev->io.baudrate = speed;
+
+ /* Disable interrupts */
+ outb( 0xff, iobase+UIRCC_CR2);
+
+ switch ( speed) {
+ case 9600:
+ case 19200:
+ case 37600:
+ case 57600:
+ case 115200:
+/* irport_open( idev->io.iobase2); */
+ irport_change_speed( idev->io.iobase2, speed);
+ modem = UIRCC_CR10_SIR;
+ break;
+ case 576000:
+
+ DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ break;
+ case 1152000:
+
+ DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ break;
+ case 4000000:
+ irport_close( idev->io.iobase2);
+ modem = UIRCC_CR10_FIR;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+ break;
+ }
+
+ /* Set appropriate speed mode */
+ outb( modem, iobase+UIRCC_CR10);
+
+ idev->netdev.tbusy = 0;
+
+ /* Enable some interrupts so we can receive frames */
+ if ( speed > 115200) {
+ /* Enable DMA single mode */
+ outb( UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET,
+ iobase+UIRCC_CR1);
+
+ /* outb( UIRCC_CR2_RECV_MASK, iobase+UIRCC_CR2); */
+ outb( 0, iobase+UIRCC_CR2);
+ uircc_dma_receive( idev);
+ }
+}
+
+/*
+ * Function uircc_hard_xmit (skb, dev)
+ *
+ * Transmit the frame!
+ *
+ */
+static int uircc_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ int mtt;
+
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ DEBUG(0, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+
+ /* Use irport for SIR speeds */
+ if ( idev->io.baudrate <= 115200) {
+ return irport_hard_xmit( skb, dev);
+ }
+
+ if ( dev->tbusy) {
+ __u8 sr3;
+
+ DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+
+ return -EBUSY;
+ }
+
+ /* Lock transmit buffer */
+ if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ memcpy( idev->tx_buff.data, skb->data, skb->len);
+
+ /* Make sure that the length is a multiple of 16 bits */
+ if ( skb->len & 0x01)
+ skb->len++;
+
+ idev->tx_buff.len = skb->len;
+ idev->tx_buff.head = idev->tx_buff.data;
+ idev->tx_buff.offset = 0;
+
+ mtt = irda_get_mtt( skb);
+
+ /* Use udelay for delays less than 50 us. */
+ if (mtt)
+ udelay( mtt);
+
+ /* Enable transmit interrupts */
+ /* outb( UIRCC_CR2_XMIT_MASK, iobase+UIRCC_CR2); */
+ outb( 0, iobase+UIRCC_CR2);
+
+ uircc_dma_write( idev, iobase);
+
+ dev_kfree_skb( skb);
+
+ return 0;
+}
+
+/*
+ * Function uircc_dma_xmit (idev, iobase)
+ *
+ * Transmit data using DMA
+ *
+ */
+static void uircc_dma_write( struct irda_device *idev, int iobase)
+{
+ struct uircc_cb *self;
+ int i;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = idev->priv;
+
+ /* Receiving disable */
+ self->cr3 &= ~UIRCC_CR3_RECV_EN;
+ outb( self->cr3, iobase+UIRCC_CR3);
+
+ setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len,
+ DMA_MODE_WRITE);
+
+ DEBUG( 0, __FUNCTION__ "residue=%d\n",
+ get_dma_residue( idev->io.dma));
+
+ idev->io.direction = IO_XMIT;
+
+ /* Set frame length */
+ outb( idev->tx_buff.len & 0xff, iobase+UIRCC_CR4); /* Low byte */
+ outb( idev->tx_buff.len >> 8, iobase+UIRCC_CR5); /* High byte */
+
+ /* Enable transmit and transmit CRC */
+ self->cr3 |= (UIRCC_CR3_XMIT_EN|UIRCC_CR3_TX_CRC_EN);
+ outb( self->cr3, iobase+UIRCC_CR3);
+}
+
+/*
+ * Function uircc_dma_xmit_complete (idev)
+ *
+ * The transfer of a frame in finished. This function will only be called
+ * by the interrupt handler
+ *
+ */
+static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun)
+{
+ struct uircc_cb *self;
+ int iobase;
+ int len;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ self = idev->priv;
+
+ iobase = idev->io.iobase;
+
+ /* Select TX counter */
+ outb( UIRCC_CR0_CNT_SWT, iobase+UIRCC_CR0);
+
+ /* Read TX length counter */
+ len = inb( iobase+UIRCC_SR4); /* Low byte */
+ len |= inb( iobase+UIRCC_SR5) << 8; /* High byte */
+
+ /* Disable transmit */
+ self->cr3 &= ~UIRCC_CR3_XMIT_EN;
+ outb( self->cr3, iobase+UIRCC_CR3);
+
+ /* Check for underrrun! */
+ if ( underrun) {
+ idev->stats.tx_errors++;
+ idev->stats.tx_fifo_errors++;
+ } else {
+ idev->stats.tx_packets++;
+ idev->stats.tx_bytes += idev->tx_buff.len;
+ }
+
+ /* Unlock tx_buff and request another frame */
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->media_busy = FALSE;
+
+ /* Tell the network layer, that we can accept more frames */
+ mark_bh( NET_BH);
+}
+
+/*
+ * Function uircc_dma_receive (idev)
+ *
+ * Get ready for receiving a frame. The device will initiate a DMA
+ * if it starts to receive a frame.
+ *
+ */
+static int uircc_dma_receive( struct irda_device *idev)
+{
+ struct uircc_cb *self;
+ int iobase;
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ DEBUG( 0, __FUNCTION__ "\n");
+
+ self = idev->priv;
+ iobase= idev->io.iobase;
+
+ /* Disable DMA */
+
+ setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize,
+ DMA_MODE_READ);
+
+ /* driver->media_busy = FALSE; */
+ idev->io.direction = IO_RECV;
+ idev->rx_buff.head = idev->rx_buff.data;
+ idev->rx_buff.offset = 0;
+
+ /* Enable receiving with CRC */
+ self->cr3 |= (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN);
+ outb( self->cr3, iobase+UIRCC_CR3);
+
+ /* Address check? */
+
+ DEBUG( 4, __FUNCTION__ "(), done!\n");
+
+ return 0;
+}
+
+/*
+ * Function uircc_dma_receive_complete (idev)
+ *
+ * Finished with receiving frames
+ *
+ *
+ */
+static int uircc_dma_receive_complete( struct irda_device *idev, int iobase)
+{
+ struct sk_buff *skb;
+ struct uircc_cb *self;
+ int len;
+
+ self = idev->priv;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ /* Check for CRC or framing error */
+ if ( inb( iobase+UIRCC_SR0) & UIRCC_SR0_RX_CRCFRM) {
+ DEBUG( 0, __FUNCTION__ "(), crc or frm error\n");
+ return -1;
+ }
+
+ /* Select receive length counter */
+ outb( 0x00, iobase+UIRCC_CR0);
+
+ /* Read frame length */
+ len = inb( iobase+UIRCC_SR4); /* Low byte */
+ len |= inb( iobase+UIRCC_SR5) << 8; /* High byte */
+
+ DEBUG( 0, __FUNCTION__ "(), len=%d\n", len);
+
+ /* Receiving disable */
+ self->cr3 &= ~UIRCC_CR3_RECV_EN;
+ outb( self->cr3, iobase+UIRCC_CR3);
+
+ skb = dev_alloc_skb( len+1);
+ if (skb == NULL) {
+ printk( KERN_INFO __FUNCTION__
+ "(), memory squeeze, dropping frame.\n");
+ /* Restore bank register */
+ return FALSE;
+ }
+
+ /* Make sure IP header gets aligned */
+ skb_reserve( skb, 1);
+
+ /* Copy frame without CRC */
+ /* if ( idev->io.baudrate < 4000000) { */
+/* skb_put( skb, len-2); */
+/* memcpy( skb->data, idev->rx_buff.head, len-2); */
+/* } else { */
+/* skb_put( skb, len-4); */
+/* memcpy( skb->data, idev->rx_buff.head, len-4); */
+/* } */
+
+ skb_put( skb, len);
+ memcpy( skb->data, idev->rx_buff.head, len);
+ idev->stats.rx_packets++;
+
+ skb->dev = &idev->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx( skb);
+
+ return TRUE;
+}
+
+/*
+ * Function uircc_interrupt (irq, dev_id, regs)
+ *
+ * An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ __u8 sr3;
+ int iobase;
+
+ struct irda_device *idev = (struct irda_device *) dev_id;
+
+ if (idev == NULL) {
+ printk( KERN_WARNING "%s: irq %d for unknown device.\n",
+ driver_name, irq);
+ return;
+ }
+
+ if (idev->io.baudrate <= 115200)
+ return irport_interrupt( irq, dev_id, regs);
+
+ iobase = idev->io.iobase;
+
+ /* Read interrupt status */
+ sr3 = inb( iobase+UIRCC_SR3);
+ if (!sr3) {
+ return;
+ }
+
+ idev->netdev.interrupt = 1;
+
+ DEBUG( 4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n",
+ inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2),
+ inb( iobase+UIRCC_SR10));
+
+ /*
+ * Check what interrupt this is. The UIRCC will not report two
+ * different interrupts at the same time!
+ */
+ switch( sr3) {
+ case UIRCC_SR3_RX_EOF: /* Check of end of frame */
+ uircc_dma_receive_complete( idev, iobase);
+ break;
+ case UIRCC_SR3_TXUR: /* Check for transmit underrun */
+ uircc_dma_xmit_complete( idev, TRUE);
+ break;
+ case UIRCC_SR3_TX_DONE:
+ uircc_dma_xmit_complete( idev, FALSE);
+ break;
+ case UIRCC_SR3_TMR_OUT:
+ /* Disable timer */
+ outb( inb( iobase+UIRCC_CR11) & ~UIRCC_CR11_TMR_EN,
+ iobase+UIRCC_CR11);
+ break;
+ default:
+ DEBUG( 0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
+ sr3);
+ break;
+ }
+
+ idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function uircc_wait_until_sent (idev)
+ *
+ * This function should put the current thread to sleep until all data
+ * have been sent, so it is safe to change the speed.
+ */
+static void uircc_wait_until_sent( struct irda_device *idev)
+{
+ /* Just delay 60 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(6);
+}
+
+/*
+ * Function uircc_is_receiving (idev)
+ *
+ * Return TRUE is we are currently receiving a frame
+ *
+ */
+static int uircc_is_receiving( struct irda_device *idev)
+{
+ int status = FALSE;
+ /* int iobase; */
+
+ ASSERT( idev != NULL, return FALSE;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+ if ( idev->io.baudrate > 115200) {
+
+ } else
+ status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+
+ return status;
+}
+
+/*
+ * Function uircc_net_init (dev)
+ *
+ * Initialize network device
+ *
+ */
+static int uircc_net_init( struct device *dev)
+{
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Setup to be a normal IrDA network device driver */
+ irda_device_setup( dev);
+
+ /* Insert overrides below this line! */
+
+ return 0;
+}
+
+
+/*
+ * Function uircc_net_open (dev)
+ *
+ * Start the device
+ *
+ */
+static int uircc_net_open( struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ if (request_irq( idev->io.irq, uircc_interrupt, 0, idev->name,
+ (void *) idev)) {
+ return -EAGAIN;
+ }
+ /*
+ * Always allocate the DMA channel after the IRQ,
+ * and clean up on failure.
+ */
+ if (request_dma(idev->io.dma, idev->name)) {
+ free_irq( idev->io.irq, idev);
+ return -EAGAIN;
+ }
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /* turn on interrupts */
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/*
+ * Function uircc_net_close (dev)
+ *
+ * Stop the device
+ *
+ */
+static int uircc_net_close(struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ disable_dma( idev->io.dma);
+
+ /* Disable interrupts */
+
+ free_irq( idev->io.irq, idev);
+ free_dma( idev->io.dma);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *
+ *
+ */
+int init_module(void)
+{
+ uircc_init();
+
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *
+ *
+ */
+void cleanup_module(void)
+{
+ uircc_cleanup();
+}
+
+#endif
+
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
new file mode 100644
index 000000000..5a7995ef7
--- /dev/null
+++ b/drivers/net/irda/w83977af_ir.c
@@ -0,0 +1,1273 @@
+/*********************************************************************
+ *
+ * Filename: w83977af_ir.c
+ * Version: 0.8
+ * Description: FIR/MIR driver for the Winbond W83977AF Super I/O chip
+ * Status: Experimental.
+ * Author: Paul VanderSpek
+ * Created at: Wed Nov 4 11:46:16 1998
+ * Modified at: Mon Dec 14 21:51:53 1998
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Corel Computer Corp.
+ * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Paul VanderSpek nor Corel Computer Corp. admit liability
+ * nor provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * If you find bugs in this file, its very likely that the same bug
+ * will also be in w83977af_ir.c since the implementations is quite
+ * similar.
+ *
+ * Notice that all functions that needs to access the chip in _any_
+ * way, must save BSR register on entry, and restore it on exit.
+ * It is _very_ important to follow this policy!
+ *
+ * __u8 bank;
+ *
+ * bank = inb( iobase+BSR);
+ *
+ * do_your_stuff_here();
+ *
+ * outb( bank, iobase+BSR);
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/w83977af.h>
+#include <net/irda/w83977af_ir.h>
+
+#define NETWINDER
+
+static char *driver_name = "w83977af_ir";
+
+#define CHIP_IO_EXTENT 8
+
+static unsigned int io[] = { 0x400, ~0, ~0, ~0 };
+static unsigned int irq[] = { 22, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0 };
+
+static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+ int status;
+ int len;
+};
+
+static struct st_fifo_entry prev;
+
+/* Some prototypes */
+static int w83977af_open( int i, unsigned int iobase, unsigned int irq,
+ unsigned int dma);
+static int w83977af_close( struct irda_device *idev);
+static int w83977af_probe( int iobase, int irq, int dma);
+static int w83977af_dma_receive(struct irda_device *idev);
+static int w83977af_dma_receive_complete(struct irda_device *idev);
+static int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev);
+static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
+static void w83977af_dma_write( struct irda_device *idev, int iobase);
+static void w83977af_change_speed( struct irda_device *idev, int baud);
+static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void w83977af_wait_until_sent( struct irda_device *idev);
+static int w83977af_is_receiving( struct irda_device *idev);
+
+static int w83977af_net_init( struct device *dev);
+static int w83977af_net_open( struct device *dev);
+static int w83977af_net_close( struct device *dev);
+
+/*
+ * Function w83977af_init ()
+ *
+ * Initialize chip. Just try to find out how many chips we are dealing with
+ * and where they are
+ */
+__initfunc(int w83977af_init(void))
+{
+ int i;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ prev.status = 0;
+
+ for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+ int ioaddr = io[i];
+ if (check_region(ioaddr, CHIP_IO_EXTENT))
+ continue;
+ if (w83977af_open( i, io[i], irq[i], dma[i]) == 0)
+ return 0;
+ }
+ return -ENODEV;
+}
+
+/*
+ * Function w83977af_cleanup ()
+ *
+ * Close all configured chips
+ *
+ */
+#ifdef MODULE
+void w83977af_cleanup(void)
+{
+ int i;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ for ( i=0; i < 4; i++) {
+ if ( dev_self[i])
+ w83977af_close( dev_self[i]);
+ }
+}
+#endif /* MODULE */
+
+/*
+ * Function w83977af_open (iobase, irq)
+ *
+ * Open driver instance
+ *
+ */
+int w83977af_open( int i, unsigned int iobase, unsigned int irq,
+ unsigned int dma)
+{
+ struct irda_device *idev;
+ int ret;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ if ( w83977af_probe( iobase, irq, dma) == -1)
+ return -1;
+
+ /*
+ * Allocate new instance of the driver
+ */
+ idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL);
+ if ( idev == NULL) {
+ printk( KERN_ERR "IrDA: Can't allocate memory for "
+ "IrDA control block!\n");
+ return -ENOMEM;
+ }
+ memset( idev, 0, sizeof(struct irda_device));
+
+ /* Need to store self somewhere */
+ dev_self[i] = idev;
+
+ /* Initialize IO */
+ idev->io.iobase = iobase;
+ idev->io.irq = irq;
+ idev->io.io_ext = CHIP_IO_EXTENT;
+ idev->io.dma = dma;
+ idev->io.fifo_size = 32;
+
+ /* Lock the port that we need */
+ ret = check_region( idev->io.iobase, idev->io.io_ext);
+ if ( ret < 0) {
+ DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ idev->io.iobase);
+ /* w83977af_cleanup( self->idev); */
+ return -ENODEV;
+ }
+ request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies( &idev->qos);
+
+ /* The only value we must override it the baudrate */
+
+ /* FIXME: The HP HDLS-1100 does not support 1152000! */
+ idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+
+ /* The HP HDLS-1100 needs 1 ms according to the specs */
+ idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
+ irda_qos_bits_to_value( &idev->qos);
+
+ /* Specify which buffer allocation policy we need */
+ idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+ idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+ idev->rx_buff.truesize = 14384;
+ idev->tx_buff.truesize = 4000;
+
+ /* Initialize callbacks */
+ idev->hard_xmit = w83977af_hard_xmit;
+ idev->change_speed = w83977af_change_speed;
+ idev->wait_until_sent = w83977af_wait_until_sent;
+ idev->is_receiving = w83977af_is_receiving;
+
+ /* Override the network functions we need to use */
+ idev->netdev.init = w83977af_net_init;
+ idev->netdev.hard_start_xmit = w83977af_hard_xmit;
+ idev->netdev.open = w83977af_net_open;
+ idev->netdev.stop = w83977af_net_close;
+
+ /* Open the IrDA device */
+ irda_device_open( idev, driver_name, NULL);
+
+ return 0;
+}
+
+/*
+ * Function w83977af_close (idev)
+ *
+ * Close driver instance
+ *
+ */
+static int w83977af_close( struct irda_device *idev)
+{
+ int iobase;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ iobase = idev->io.iobase;
+
+ /* enter PnP configuration mode */
+ w977_efm_enter();
+
+ w977_select_device(W977_DEVICE_IR);
+
+ /* Deactivate device */
+ w977_write_reg(0x30, 0x00);
+
+ w977_efm_exit();
+
+ /* Release the PORT that this driver is using */
+ DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
+ idev->io.iobase);
+ release_region( idev->io.iobase, idev->io.io_ext);
+
+ irda_device_close( idev);
+
+ return 0;
+}
+
+/*
+ * Function w83977af_probe (iobase, irq, dma)
+ *
+ * Returns non-negative on success.
+ *
+ */
+int w83977af_probe( int iobase, int irq, int dma)
+{
+ int version;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ /* Enter PnP configuration mode */
+ w977_efm_enter();
+
+ w977_select_device(W977_DEVICE_IR);
+
+ /* Configure PnP port, IRQ, and DMA channel */
+ w977_write_reg(0x60, (iobase >> 8) & 0xff);
+ w977_write_reg(0x61, (iobase) & 0xff);
+ w977_write_reg(0x70, 0x06);
+#ifdef NETWINDER
+ w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */
+#else
+ w977_write_reg(0x74, dma);
+#endif
+ w977_write_reg(0x75, dma); /* Disable Tx DMA */
+
+ /* Set append hardware CRC, enable IR bank selection */
+ w977_write_reg(0xf0, APEDCRC|ENBNKSEL);
+
+ /* Activate device */
+ w977_write_reg(0x30, 0x01);
+
+ w977_efm_exit();
+
+ /* Disable Advanced mode */
+ switch_bank( iobase, SET2);
+ outb(iobase+2, 0x00);
+
+ /* Turn on UART (global) interrupts */
+ switch_bank( iobase, SET0);
+ outb( HCR_EN_IRQ, iobase+HCR);
+
+ /* Switch to advanced mode */
+ switch_bank( iobase, SET2);
+ outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
+
+ /* Set default IR-mode */
+ switch_bank( iobase, SET0);
+ outb( HCR_SIR, iobase+HCR);
+
+ /* Read the Advanced IR ID */
+ switch_bank(iobase, SET3);
+ version = inb( iobase+AUID);
+
+ /* Should be 0x1? */
+ if (0x10 != (version & 0xf0)) {
+ DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+ return -1;
+ }
+
+ /* Set FIFO size to 32 */
+ switch_bank( iobase, SET2);
+ outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);
+
+ /* Set FIFO threshold to TX17, RX16 */
+ switch_bank(iobase, SET0);
+ outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR);
+/* outb( 0xa7, iobase+UFR); */
+
+ /* Receiver frame length */
+ switch_bank( iobase, SET4);
+ outb( 2048 & 0xff, iobase+6);
+ outb(( 2048 >> 8) & 0x1f, iobase+7);
+
+ /*
+ * Init HP HSDL-1100 transceiver.
+ *
+ * Set IRX_MSL since we have 2 * receive paths IRRX, and
+ * IRRXH. Clear IRSL0D since we want IRSL0 * to be a input pin used
+ * for IRRXH
+ *
+ * IRRX pin 37 connected to receiver
+ * IRTX pin 38 connected to transmitter
+ * FIRRX pin 39 connected to receiver (IRSL0)
+ * CIRRX pin 40 connected to pin 37
+ */
+ switch_bank( iobase, SET7);
+ outb( 0x40, iobase+7);
+
+ DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
+
+ return 0;
+}
+
+/*
+ * Function w83977af_change_speed (idev, baud)
+ *
+ * Change the speed of the device
+ *
+ */
+void w83977af_change_speed( struct irda_device *idev, int speed)
+{
+ int ir_mode = HCR_SIR;
+ int iobase;
+ __u8 set;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ iobase = idev->io.iobase;
+
+ /* Update accounting for new speed */
+ idev->io.baudrate = speed;
+
+ /* Save current bank */
+ set = inb( iobase+SSR);
+
+ /* Disable interrupts */
+ switch_bank( iobase, SET0);
+ outb( 0, iobase+ICR);
+
+ /* Select Set 2 */
+ switch_bank( iobase, SET2);
+
+ outb( 0x00, iobase+ABHL);
+ switch ( speed) {
+ case 9600: outb( 0x0c, iobase+ABLL); break;
+ case 19200: outb( 0x06, iobase+ABLL); break;
+ case 37600: outb( 0x03, iobase+ABLL); break;
+ case 57600: outb( 0x02, iobase+ABLL); break;
+ case 115200: outb( 0x01, iobase+ABLL); break;
+ case 576000:
+ ir_mode = HCR_MIR_576;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ break;
+ case 1152000:
+ ir_mode = HCR_MIR_1152;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ break;
+ case 4000000:
+ ir_mode = HCR_FIR;
+ DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ break;
+ default:
+ ir_mode = HCR_FIR;
+ DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+ break;
+ }
+
+ /* Set speed mode */
+ switch_bank(iobase, SET0);
+ outb( ir_mode, iobase+HCR);
+
+ /* set FIFO size to 32 */
+ switch_bank( iobase, SET2);
+ outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);
+
+ /* set FIFO threshold to TX17, RX16 */
+ switch_bank(iobase, SET0);
+ outb( UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+
+ idev->netdev.tbusy = 0;
+
+ /* Enable some interrupts so we can receive frames */
+ switch_bank(iobase, SET0);
+ if ( speed > 115200) {
+ outb( ICR_EFSFI, iobase+ICR);
+ w83977af_dma_receive( idev);
+ } else
+ outb( ICR_ERBRI, iobase+ICR);
+
+ /* Restore SSR */
+ outb( set, iobase+SSR);
+}
+
+/*
+ * Function w83977af_hard_xmit (skb, dev)
+ *
+ * Sets up a DMA transfer to send the current frame.
+ *
+ */
+int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ __u8 set;
+ int mtt;
+
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+
+ if ( dev->tbusy) {
+ DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+
+ return -EBUSY;
+ }
+
+ /* Lock transmit buffer */
+ if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ /* Decide if we should use PIO or DMA transfer */
+ if ( idev->io.baudrate > 115200) {
+ memcpy( idev->tx_buff.data, skb->data, skb->len);
+ idev->tx_buff.len = skb->len;
+ idev->tx_buff.head = idev->tx_buff.data;
+ idev->tx_buff.offset = 0;
+
+ mtt = irda_get_mtt( skb);
+ if ( mtt > 50) {
+ /* Adjust for timer resolution */
+ mtt /= 1000+1;
+
+ /* Setup timer */
+ switch_bank( iobase, SET4);
+ outb( mtt & 0xff, iobase+TMRL);
+ outb(( mtt >> 8) & 0x0f, iobase+TMRH);
+
+ /* Start timer */
+ outb( IR_MSL_EN_TMR, iobase+IR_MSL);
+ idev->io.direction = IO_XMIT;
+
+ /* Enable timer interrupt */
+ switch_bank( iobase, SET0);
+ outb( ICR_ETMRI, iobase+ICR);
+ } else {
+ if ( mtt)
+ udelay( mtt);
+
+ /* Enable DMA interrupt */
+ switch_bank( iobase, SET0);
+ outb( ICR_EDMAI, iobase+ICR);
+ w83977af_dma_write( idev, iobase);
+ }
+ } else {
+ idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data,
+ idev->tx_buff.truesize);
+
+ idev->tx_buff.offset = 0;
+ idev->tx_buff.head = idev->tx_buff.data;
+
+ /* Add interrupt on tx low level (will fire immediately) */
+ switch_bank( iobase, SET0);
+ outb( ICR_ETXTHI, iobase+ICR);
+ }
+ dev_kfree_skb( skb);
+
+ /* Restore set register */
+ outb( set, iobase+SSR);
+
+ return 0;
+}
+
+
+/*
+ * Function w83977af_dma_write (idev, iobase)
+ *
+ *
+ *
+ */
+static void w83977af_dma_write( struct irda_device *idev, int iobase)
+{
+ __u8 set;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ /* Disable DMA */
+ switch_bank(iobase, SET0);
+ outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
+ setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len,
+ DMA_MODE_WRITE);
+
+ /* idev->media_busy = TRUE; */
+ idev->io.direction = IO_XMIT;
+
+ /* Choose transmit DMA channel */
+ switch_bank(iobase, SET2);
+ outb( inb( iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL,
+ iobase+ADCR1);
+
+ /* Enable DMA */
+ switch_bank( iobase, SET0);
+ outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+
+ /* Restore set register */
+ outb( set, iobase+SSR);
+}
+
+/*
+ * Function w83977af_pio_write (iobase, buf, len, fifo_size)
+ *
+ *
+ *
+ */
+static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size)
+{
+ int actual = 0;
+ __u8 set;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /* Save current bank */
+ set = inb( iobase+SSR);
+
+ switch_bank( iobase, SET0);
+ if (!( inb_p( iobase+USR) & USR_TSRE)) {
+ DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+
+ fifo_size -= 17;
+ DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+ }
+
+ /* Fill FIFO with current frame */
+ while (( fifo_size-- > 0) && (actual < len)) {
+ /* Transmit next byte */
+ outb( buf[actual++], iobase+TBR);
+ }
+
+ DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ fifo_size, actual, len);
+
+ /* Restore bank */
+ outb( set, iobase+SSR);
+
+ return actual;
+}
+
+/*
+ * Function w83977af_dma_xmit_complete (idev)
+ *
+ * The transfer of a frame in finished. So do the necessary things
+ *
+ *
+ */
+void w83977af_dma_xmit_complete( struct irda_device *idev)
+{
+ int iobase;
+ __u8 set;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ iobase = idev->io.iobase;
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ /* Disable DMA */
+ switch_bank(iobase, SET0);
+ outb( inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
+ /* Check for underrrun! */
+ if ( inb( iobase+AUDR) & AUDR_UNDR) {
+ DEBUG( 0, __FUNCTION__ "(), Transmit underrun!\n");
+
+ idev->stats.tx_errors++;
+ idev->stats.tx_fifo_errors++;
+
+ /* Clear bit, by writing 1 to it */
+ outb( AUDR_UNDR, iobase+AUDR);
+ } else
+ idev->stats.tx_packets++;
+
+ /* Unlock tx_buff and request another frame */
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->media_busy = FALSE;
+
+ /* Tell the network layer, that we want more frames */
+ mark_bh( NET_BH);
+
+ /* Restore set */
+ outb( set, iobase+SSR);
+}
+
+/*
+ * Function w83977af_dma_receive (idev)
+ *
+ * Get ready for receiving a frame. The device will initiate a DMA
+ * if it starts to receive a frame.
+ *
+ */
+int w83977af_dma_receive( struct irda_device *idev)
+{
+ int iobase;
+ __u8 set;
+#ifdef NETWINDER
+ unsigned long flags;
+ __u8 hcr;
+#endif
+
+ ASSERT( idev != NULL, return -1;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ DEBUG( 0, __FUNCTION__ "\n");
+
+ iobase= idev->io.iobase;
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ /* Disable DMA */
+ switch_bank( iobase, SET0);
+ outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
+#ifdef NETWINDER
+ save_flags(flags);
+ cli();
+
+ disable_dma( idev->io.dma);
+ clear_dma_ff( idev->io.dma);
+ set_dma_mode( idev->io.dma, DMA_MODE_READ);
+ set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data));
+ set_dma_count( idev->io.dma, idev->rx_buff.truesize);
+#else
+ setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize,
+ DMA_MODE_READ);
+#endif
+ /* driver->media_busy = FALSE; */
+ idev->io.direction = IO_RECV;
+ idev->rx_buff.head = idev->rx_buff.data;
+ idev->rx_buff.offset = 0;
+
+ /*
+ * Reset Rx FIFO. This will also flush the ST_FIFO, it's very
+ * important that we don't reset the Tx FIFO since it might not
+ * be finished transmitting yet
+ */
+ outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+ prev.status = 0;
+
+ /* Choose DMA Rx, DMA Fairness, and Advanced mode */
+ switch_bank(iobase, SET2);
+ outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL,
+ iobase+ADCR1);
+
+ /* Enable DMA */
+ switch_bank(iobase, SET0);
+#ifdef NETWINDER
+ hcr = inb( iobase+HCR);
+ enable_dma( idev->io.dma);
+ outb( hcr | HCR_EN_DMA, iobase+HCR);
+ restore_flags(flags);
+#else
+ outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+#endif
+
+ /* Restore set */
+ outb( set, iobase+SSR);
+
+ DEBUG( 4, __FUNCTION__ "(), done!\n");
+
+ return 0;
+}
+
+/*
+ * Function w83977af_receive_complete (idev)
+ *
+ * Finished with receiving a frame
+ *
+ */
+int w83977af_dma_receive_complete(struct irda_device *idev)
+{
+ struct sk_buff *skb;
+ int len;
+ int iobase;
+ __u8 set;
+ __u8 status;
+
+ DEBUG( 0, __FUNCTION__ "\n");
+
+ iobase = idev->io.iobase;
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ iobase = idev->io.iobase;
+
+ switch_bank(iobase, SET5);
+ if ( prev.status & FS_FO_FSFDR) {
+ status = prev.status;
+ len = prev.len;
+
+ prev.status = 0;
+ } else {
+ status = inb( iobase+FS_FO);
+ len = inb( iobase+RFLFL);
+ len |= inb( iobase+RFLFH) << 8;
+ }
+
+ while ( status & FS_FO_FSFDR) {
+ /* Check for errors */
+ if ( status & FS_FO_ERR_MSK) {
+ if ( status & FS_FO_LST_FR) {
+ /* Add number of lost frames to stats */
+ idev->stats.rx_errors += len;
+ } else {
+ /* Skip frame */
+ idev->stats.rx_errors++;
+
+ idev->rx_buff.offset += len;
+ idev->rx_buff.head += len;
+
+ if ( status & FS_FO_MX_LEX)
+ idev->stats.rx_length_errors++;
+
+ if ( status & FS_FO_PHY_ERR)
+ idev->stats.rx_frame_errors++;
+
+ if ( status & FS_FO_CRC_ERR)
+ idev->stats.rx_crc_errors++;
+ }
+ /* The errors below can be reported in both cases */
+ if ( status & FS_FO_RX_OV)
+ idev->stats.rx_fifo_errors++;
+
+ if ( status & FS_FO_FSF_OV)
+ idev->stats.rx_fifo_errors++;
+
+ } else {
+ /* Check if we have transfered all data to memory */
+ switch_bank(iobase, SET0);
+ if ( inb( iobase+USR) & USR_RDR) {
+ /* Put this entry back in fifo */
+ prev.status = status;
+ prev.len = len;
+
+ /* Restore set register */
+ outb( set, iobase+SSR);
+
+ return FALSE; /* I'll be back! */
+ }
+
+ skb = dev_alloc_skb( len+1);
+ if (skb == NULL) {
+ printk( KERN_INFO __FUNCTION__
+ "(), memory squeeze, dropping frame.\n");
+ /* Restore set register */
+ outb( set, iobase+SSR);
+
+ return FALSE;
+ }
+
+ /* Align to 20 bytes */
+ skb_reserve( skb, 1);
+
+ /* Copy frame without CRC */
+ if ( idev->io.baudrate < 4000000) {
+ skb_put( skb, len-2);
+ memcpy( skb->data, idev->rx_buff.head, len-2);
+ } else {
+ skb_put( skb, len-4);
+ memcpy( skb->data, idev->rx_buff.head, len-4);
+ }
+
+ /* Move to next frame */
+ idev->rx_buff.offset += len;
+ idev->rx_buff.head += len;
+
+ skb->dev = &idev->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx( skb);
+ idev->stats.rx_packets++;
+ }
+ /* Read next entry in ST_FIFO */
+ switch_bank(iobase, SET5);
+ status = inb( iobase+FS_FO);
+ len = inb( iobase+RFLFL);
+ len |= inb( iobase+RFLFH) << 8;
+ }
+ /* Restore set register */
+ outb( set, iobase+SSR);
+
+ return TRUE;
+}
+
+/*
+ * Function pc87108_pio_receive (idev)
+ *
+ * Receive all data in receiver FIFO
+ *
+ */
+static void w83977af_pio_receive( struct irda_device *idev)
+{
+ __u8 byte = 0x00;
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( idev != NULL, return;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+ iobase = idev->io.iobase;
+
+ if ( idev->rx_buff.len == 0) {
+ idev->rx_buff.head = idev->rx_buff.data;
+ }
+
+ /* Receive all characters in Rx FIFO */
+ do {
+ byte = inb( iobase+RBR);
+ async_unwrap_char( idev, byte);
+
+ } while ( inb( iobase+USR) & USR_RDR); /* Data available */
+}
+
+/*
+ * Function w83977af_sir_interrupt (idev, eir)
+ *
+ * Handle SIR interrupt
+ *
+ */
+static __u8 w83977af_sir_interrupt( struct irda_device *idev, int isr)
+{
+ int len;
+ int actual;
+ __u8 new_icr = 0;
+
+ DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr);
+
+ /* Transmit FIFO low on data */
+ if ( isr & ISR_TXTH_I) {
+ /* Write data left in transmit buffer */
+ len = idev->tx_buff.len - idev->tx_buff.offset;
+
+ ASSERT( len > 0, return 0;);
+ actual = w83977af_pio_write( idev->io.iobase,
+ idev->tx_buff.head,
+ len, idev->io.fifo_size);
+ idev->tx_buff.offset += actual;
+ idev->tx_buff.head += actual;
+
+ idev->io.direction = IO_XMIT;
+ ASSERT( actual <= len, return 0;);
+ /* Check if finished */
+ if ( actual == len) {
+ DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+ idev->netdev.tbusy = 0; /* Unlock */
+ idev->stats.tx_packets++;
+
+ /* Schedule network layer */
+ mark_bh(NET_BH);
+
+ new_icr |= ICR_ETBREI;
+ } else
+ new_icr |= ICR_ETXTHI;
+ }
+ /* Check if transmission has completed */
+ if ( isr & ISR_TXEMP_I) {
+
+ /* Turn around and get ready to receive some data */
+ idev->io.direction = IO_RECV;
+ new_icr |= ICR_ERBRI;
+ }
+
+ /* Rx FIFO threshold or timeout */
+ if ( isr & ISR_RXTH_I) {
+ w83977af_pio_receive( idev);
+
+ /* Keep receiving */
+ new_icr |= ICR_ERBRI;
+ }
+ return new_icr;
+}
+
+/*
+ * Function pc87108_fir_interrupt (idev, eir)
+ *
+ * Handle MIR/FIR interrupt
+ *
+ */
+static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr)
+{
+ __u8 new_icr = 0;
+ __u8 set;
+ int iobase;
+
+ DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr);
+
+ iobase = idev->io.iobase;
+
+ set = inb( iobase+SSR);
+
+ /* End of frame detected in FIFO */
+ if ( isr & (ISR_FEND_I|ISR_FSF_I)) {
+ if ( w83977af_dma_receive_complete( idev)) {
+
+ new_icr |= ICR_EFSFI;
+ } else {
+ /* DMA not finished yet */
+
+ /* Set timer value, resolution 1 ms */
+ switch_bank( iobase, SET4);
+ outb( 0x01, iobase+TMRL); /* 1 ms */
+ outb( 0x00, iobase+TMRH);
+
+ /* Start timer */
+ outb( IR_MSL_EN_TMR, iobase+IR_MSL);
+
+ new_icr |= ICR_ETMRI;
+ }
+ }
+ /* Timer finished */
+ if ( isr & ISR_TMR_I) {
+ /* Disable timer */
+ switch_bank( iobase, SET4);
+ outb( 0, iobase+IR_MSL);
+
+ /* Clear timer event */
+ /* switch_bank(iobase, SET0); */
+/* outb( ASCR_CTE, iobase+ASCR); */
+
+ /* Check if this is a TX timer interrupt */
+ if ( idev->io.direction == IO_XMIT) {
+ w83977af_dma_write( idev, iobase);
+
+ new_icr |= ICR_EDMAI;
+ } else {
+ /* Check if DMA has now finished */
+ w83977af_dma_receive_complete( idev);
+
+ new_icr |= ICR_EFSFI;
+ }
+ }
+ /* Finished with DMA */
+ if ( isr & ISR_DMA_I) {
+ w83977af_dma_xmit_complete( idev);
+
+ /* Check if there are more frames to be transmitted */
+ if ( irda_device_txqueue_empty( idev)) {
+
+ /* Prepare for receive */
+ w83977af_dma_receive( idev);
+ new_icr = ICR_EFSFI;
+ }
+ }
+
+ /* Restore set */
+ outb( set, iobase+SSR);
+
+ return new_icr;
+}
+
+/*
+ * Function pc87108_interrupt (irq, dev_id, regs)
+ *
+ * An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ __u8 set, icr, isr;
+ int iobase;
+
+ struct irda_device *idev = (struct irda_device *) dev_id;
+
+ if ( idev == NULL) {
+ printk( KERN_WARNING "%s: irq %d for unknown device.\n",
+ driver_name, irq);
+ return;
+ }
+
+ idev->netdev.interrupt = 1;
+
+ iobase = idev->io.iobase;
+
+ /* Save current bank */
+ set = inb( iobase+SSR);
+ switch_bank( iobase, SET0);
+
+ icr = inb( iobase+ICR);
+ isr = inb( iobase+ISR) & icr; /* Mask out the interesting ones */
+
+ outb( 0, iobase+ICR); /* Disable interrupts */
+
+ if ( isr) {
+ /* Dispatch interrupt handler for the current speed */
+ if ( idev->io.baudrate > 115200)
+ icr = w83977af_fir_interrupt( idev, isr);
+ else
+ icr = w83977af_sir_interrupt( idev, isr);
+ }
+
+ outb( icr, iobase+ICR); /* Restore (new) interrupts */
+ outb( set, iobase+SSR); /* Restore bank register */
+
+ idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function w83977af_wait_until_sent (idev)
+ *
+ * This function should put the current thread to sleep until all data
+ * have been sent, so it is safe to f.eks. change the speed.
+ */
+static void w83977af_wait_until_sent( struct irda_device *idev)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(6);
+}
+
+/*
+ * Function w83977af_is_receiving (idev)
+ *
+ * Return TRUE is we are currently receiving a frame
+ *
+ */
+static int w83977af_is_receiving( struct irda_device *idev)
+{
+ int status = FALSE;
+ int iobase;
+ __u8 set;
+
+ ASSERT( idev != NULL, return FALSE;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+ if ( idev->io.baudrate > 115200) {
+ iobase = idev->io.iobase;
+
+ /* Check if rx FIFO is not empty */
+ set = inb( iobase+SSR);
+ switch_bank( iobase, SET2);
+ if (( inb( iobase+RXFDTH) & 0x3f) != 0) {
+ /* We are receiving something */
+ status = TRUE;
+ }
+ outb( set, iobase+SSR);
+ } else
+ status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+
+ return status;
+}
+
+/*
+ * Function w83977af_net_init (dev)
+ *
+ *
+ *
+ */
+static int w83977af_net_init( struct device *dev)
+{
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ /* Set up to be a normal IrDA network device driver */
+ irda_device_setup( dev);
+
+ /* Insert overrides below this line! */
+
+ return 0;
+}
+
+
+/*
+ * Function w83977af_net_open (dev)
+ *
+ * Start the device
+ *
+ */
+static int w83977af_net_open( struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ __u8 set;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ if (request_irq( idev->io.irq, w83977af_interrupt, 0, idev->name,
+ (void *) idev)) {
+ return -EAGAIN;
+ }
+ /*
+ * Always allocate the DMA channel after the IRQ,
+ * and clean up on failure.
+ */
+ if (request_dma(idev->io.dma, idev->name)) {
+ free_irq( idev->io.irq, idev);
+ return -EAGAIN;
+ }
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ /* Enable some interrupts so we can receive frames again */
+ switch_bank(iobase, SET0);
+ if ( idev->io.baudrate > 115200) {
+ outb( ICR_EFSFI, iobase+ICR);
+ w83977af_dma_receive( idev);
+ } else
+ outb( ICR_ERBRI, iobase+ICR);
+
+ /* Restore bank register */
+ outb( set, iobase+SSR);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/*
+ * Function w83977af_net_close (dev)
+ *
+ * Stop the device
+ *
+ */
+static int w83977af_net_close(struct device *dev)
+{
+ struct irda_device *idev;
+ int iobase;
+ __u8 set;
+
+ DEBUG( 0, __FUNCTION__ "()\n");
+
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ ASSERT( dev != NULL, return -1;);
+ idev = (struct irda_device *) dev->priv;
+
+ ASSERT( idev != NULL, return 0;);
+ ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+ iobase = idev->io.iobase;
+
+ disable_dma( idev->io.dma);
+
+ /* Save current set */
+ set = inb( iobase+SSR);
+
+ /* Disable interrupts */
+ switch_bank( iobase, SET0);
+ outb( 0, iobase+ICR);
+
+ free_irq( idev->io.irq, idev);
+ free_dma( idev->io.dma);
+
+ /* Restore bank register */
+ outb( set, iobase+SSR);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *
+ *
+ */
+int init_module(void)
+{
+ w83977af_init();
+
+ return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *
+ *
+ */
+void cleanup_module(void)
+{
+ w83977af_cleanup();
+}
+
+#endif
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 15f7f9ad7..659983655 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -1,6 +1,6 @@
-/* lance.c: An AMD LANCE ethernet driver for linux. */
+/* lance.c: An AMD LANCE/PCnet ethernet driver for Linux. */
/*
- Written 1993,1994,1995 by Donald Becker.
+ Written/copyright 1993-1998 by Donald Becker.
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
@@ -8,13 +8,12 @@
of the GNU Public License, incorporated herein by reference.
This driver is for the Allied Telesis AT1500 and HP J2405A, and should work
- with most other LANCE-based bus-master (NE2100 clone) ethercards.
+ with most other LANCE-based bus-master (NE2100/NE2500) ethercards.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
Fixing alignment problem with 1.3.* kernel and some minor changes
by Andrey V. Savochkin, 1996.
@@ -28,14 +27,28 @@
But I should to inform you that I'm not an expert in the LANCE card
and it may occurs that you will receive no answer on your mail
to Donald Becker. I didn't receive any answer on all my letters
- to him. Who knows why... But may be you are more lucky? ;-)
+ to him. Who knows why... But may be you are more lucky? ;->
SAW
- Fixed 7990 autoIRQ failure and reversed unneeded alignment. 8/20/96 djb
+
+ Thomas Bogendoerfer (tsbogend@bigbug.franken.de):
+ - added support for Linux/Alpha, but removed most of it, because
+ it worked only for the PCI chip.
+ - added hook for the 32bit lance driver
+ - added PCnetPCI II (79C970A) to chip table
+ Paul Gortmaker (gpg109@rsphy1.anu.edu.au):
+ - hopefully fix above so Linux/Alpha can use ISA cards too.
+ 8/20/96 Fixed 7990 autoIRQ failure and reversed unneeded alignment -djb
+ v1.12 10/27/97 Module support -djb
+ v1.14 2/3/98 Module support modified, made PCI support optional -djb
+
+ Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from
+ the 2.1 version of the old driver - Alan Cox
*/
-static const char *version = "lance.c:v1.09 Aug 20 1996 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
+static const char *version = "lance.c:v1.14ac 1998/11/20 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -54,13 +67,9 @@ static const char *version = "lance.c:v1.09 Aug 20 1996 dplatt@3do.com, becker@c
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-static unsigned int lance_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
-void lance_probe1(int ioaddr);
-
-#ifdef HAVE_DEVLIST
-struct netdev_entry lance_drv =
-{"lance", lance_probe1, LANCE_TOTAL_SIZE, lance_portlist};
-#endif
+static unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0};
+int lance_probe(struct device *dev);
+int lance_probe1(struct device *dev, int ioaddr, int irq, int options);
#ifdef LANCE_DEBUG
int lance_debug = LANCE_DEBUG;
@@ -96,7 +105,7 @@ of the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is
probed for by enabling each free DMA channel in turn and checking if
initialization succeeds.
-The HP-J2405A board is an exception: with this board it's easy to read the
+The HP-J2405A board is an exception: with this board it is easy to read the
EEPROM-set values for the base, IRQ, and DMA. (Of course you must already
_know_ the base address -- that field is for writing the EEPROM.)
@@ -147,36 +156,19 @@ queue slot is empty, it clears the tbusy flag when finished otherwise it sets
the 'lp->tx_full' flag.
The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so
+from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so
we can't avoid the interrupt overhead by having the Tx routine reap the Tx
stats.) After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the
+the 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the
tx_full and tbusy flags.
*/
-/* Memory accessed from LANCE card must be aligned on 8-byte boundaries.
- But we can't believe that kmalloc()'ed memory satisfies it. -- SAW */
-#define LANCE_KMALLOC(x) \
- ((void *) (((unsigned long)kmalloc((x)+7, GFP_DMA | GFP_KERNEL)+7) & ~7))
-
-/*
- * Changes:
- * Thomas Bogendoerfer (tsbogend@alpha.franken.de):
- * - added support for Linux/Alpha, but removed most of it, because
- * it worked only for the PCI chip.
- * - added hook for the 32bit lance driver
- * - added PCnetPCI II (79C970A) to chip table
- * - made 32bit driver standalone
- * - changed setting of autoselect bit
- *
- * Paul Gortmaker (gpg109@rsphy1.anu.edu.au):
- * - hopefully fix above so Linux/Alpha can use ISA cards too.
- */
-
/* Set the number of Tx and Rx buffers, using Log_2(# buffers).
Reasonable default values are 16 Tx buffers, and 16 Rx buffers.
- That translates to 4 and 4 (16 == 2^^4). */
+ That translates to 4 and 4 (16 == 2^^4).
+ This is a compile-time option for efficiency.
+ */
#ifndef LANCE_LOG_TX_BUFFERS
#define LANCE_LOG_TX_BUFFERS 4
#define LANCE_LOG_RX_BUFFERS 4
@@ -230,6 +222,8 @@ struct lance_private {
const char *name;
/* The saved address of a sent-in-place packet/buffer, for skfree(). */
struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ /* The addresses of receive-in-place skbuffs. */
+ struct sk_buff* rx_skbuff[RX_RING_SIZE];
unsigned long rx_buffs; /* Address of Rx and Tx buffers. */
/* Tx low-memory "bounce buffer" address. */
char (*tx_bounce_buffs)[PKT_BUF_SZ];
@@ -247,7 +241,6 @@ struct lance_private {
#define LANCE_MUST_REINIT_RING 0x00000004
#define LANCE_MUST_UNRESET 0x00000008
#define LANCE_HAS_MISSED_FRAME 0x00000010
-#define PCNET32_POSSIBLE 0x00000020
/* A mapping from the chip ID number to the part number and features.
These are from the datasheets -- in real life the '970 version
@@ -267,21 +260,15 @@ static struct lance_chip_type {
LANCE_HAS_MISSED_FRAME},
{0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
+ LANCE_HAS_MISSED_FRAME},
/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call
it the PCnet32. */
{0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
+ LANCE_HAS_MISSED_FRAME},
{0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
- {0x2623, "PCnet/FAST 79C971", /* 79C971 PCInetFAST. */
- LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
- {0x2624, "PCnet/FAST+ 79C972", /* 79C972 PCInetFAST+. */
- LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
- LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
+ LANCE_HAS_MISSED_FRAME},
{0x0, "PCnet (unknown)",
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
@@ -298,7 +285,7 @@ static unsigned char lance_need_isa_bounce_buffers = 1;
static int lance_open(struct device *dev);
static int lance_open_fail(struct device *dev);
-static void lance_init_ring(struct device *dev);
+static void lance_init_ring(struct device *dev, int mode);
static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
static int lance_rx(struct device *dev);
static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -308,24 +295,88 @@ static void set_multicast_list(struct device *dev);
-/* This lance probe is unlike the other board probes in 1.0.*. The LANCE may
- have to allocate a contiguous low-memory region for bounce buffers.
- This requirement is satisfied by having the lance initialization occur
- before the memory management system is started, and thus well before the
- other probes. */
+#ifdef MODULE
+#define MAX_CARDS 8 /* Max number of interfaces (cards) per module */
+#define IF_NAMELEN 8 /* # of chars for storing dev->name */
+
+static int io[MAX_CARDS] = { 0, };
+static int dma[MAX_CARDS] = { 0, };
+static int irq[MAX_CARDS] = { 0, };
-__initfunc(int lance_init(void))
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
+
+static char ifnames[MAX_CARDS][IF_NAMELEN] = { {0, }, };
+static struct device dev_lance[MAX_CARDS] =
+{{
+ 0, /* device name is inserted by linux/drivers/net/net_init.c */
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL}};
+
+int init_module(void)
+{
+ int this_dev, found = 0;
+
+ for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
+ struct device *dev = &dev_lance[this_dev];
+ dev->name = ifnames[this_dev];
+ dev->irq = irq[this_dev];
+ dev->base_addr = io[this_dev];
+ dev->dma = dma[this_dev];
+ dev->init = lance_probe;
+ if (io[this_dev] == 0) {
+ if (this_dev != 0) break; /* only complain once */
+ printk(KERN_NOTICE "lance.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n");
+ return -EPERM;
+ }
+ if (register_netdev(dev) != 0) {
+ printk(KERN_WARNING "lance.c: No PCnet/LANCE card found (i/o = 0x%x).\n", io[this_dev]);
+ if (found != 0) return 0; /* Got at least one. */
+ return -ENXIO;
+ }
+ found++;
+ }
+
+ return 0;
+}
+
+void cleanup_module(void)
{
- int *port;
+ int this_dev;
+
+ for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
+ struct device *dev = &dev_lance[this_dev];
+ if (dev->priv != NULL) {
+ kfree(dev->priv);
+ dev->priv = NULL;
+ free_dma(dev->dma);
+ release_region(dev->base_addr, LANCE_TOTAL_SIZE);
+ unregister_netdev(dev);
+ }
+ }
+}
+#endif /* MODULE */
- if (virt_to_bus(high_memory) <= 16*1024*1024)
+/* Starting in v2.1.*, the LANCE/PCnet probe is now similar to the other
+ board probes now that kmalloc() can allocate ISA DMA-able regions.
+ This also allows the LANCE driver to be used as a module.
+ */
+int lance_probe(struct device *dev)
+{
+ int *port, result;
+
+ if (high_memory <= phys_to_virt(16*1024*1024))
lance_need_isa_bounce_buffers = 0;
-#if defined(CONFIG_PCI) && !(defined(CONFIG_PCNET32) || defined(CONFIG_PCNET32_MODULE))
- if (pci_present()) {
- struct pci_dev *pdev = NULL;
+#if defined(CONFIG_PCI)
+ if (pci_present())
+ {
+ struct pci_dev *pdev = NULL;
if (lance_debug > 1)
- printk("lance.c: PCI is present, checking for devices...\n");
+ printk("lance.c: PCI bios is present, checking for devices...\n");
+
while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) {
unsigned int pci_ioaddr;
unsigned short pci_command;
@@ -344,8 +395,9 @@ __initfunc(int lance_init(void))
}
printk("Found PCnet/PCI at %#x, irq %d.\n",
pci_ioaddr, pci_irq_line);
- lance_probe1(pci_ioaddr);
+ result = lance_probe1(dev, pci_ioaddr, pci_irq_line, 0);
pci_irq_line = 0;
+ if (!result) return 0;
}
}
#endif /* defined(CONFIG_PCI) */
@@ -359,16 +411,17 @@ __initfunc(int lance_init(void))
char offset15, offset14 = inb(ioaddr + 14);
if ((offset14 == 0x52 || offset14 == 0x57) &&
- ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))
- lance_probe1(ioaddr);
+ ((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44)) {
+ result = lance_probe1(dev, ioaddr, 0, 0);
+ if ( !result ) return 0;
+ }
}
}
- return 0;
+ return -ENODEV;
}
-__initfunc(void lance_probe1(int ioaddr))
+__initfunc(int lance_probe1(struct device *dev, int ioaddr, int irq, int options))
{
- struct device *dev;
struct lance_private *lp;
short dma_channels; /* Mark spuriously-busy DMA channels */
int i, reset_val, lance_version;
@@ -406,7 +459,7 @@ __initfunc(void lance_probe1(int ioaddr))
outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */
if (inw(ioaddr+LANCE_DATA) != 0x0004)
- return;
+ return -ENODEV;
/* Get the version of the chip. */
outw(88, ioaddr+LANCE_ADDR);
@@ -419,24 +472,17 @@ __initfunc(void lance_probe1(int ioaddr))
if (lance_debug > 2)
printk(" LANCE chip version is %#x.\n", chip_version);
if ((chip_version & 0xfff) != 0x003)
- return;
+ return -ENODEV;
chip_version = (chip_version >> 12) & 0xffff;
for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) {
if (chip_table[lance_version].id_number == chip_version)
break;
}
}
-
-#if defined(CONFIG_PCNET32) || defined (CONFIG_PCNET32_MODULE)
- /*
- * if pcnet32 is configured and the chip is capable of 32bit mode
- * leave the card alone
- */
- if (chip_table[lance_version].flags & PCNET32_POSSIBLE)
- return;
-#endif
- dev = init_etherdev(0, 0);
+ /* We can't use init_etherdev() to allocate dev->priv because it must
+ a ISA DMA-able region. */
+ dev = init_etherdev(dev, 0);
dev->open = lance_open_fail;
chipname = chip_table[lance_version].name;
printk("%s: %s at %#3x,", dev->name, chipname, ioaddr);
@@ -450,6 +496,7 @@ __initfunc(void lance_probe1(int ioaddr))
request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name);
/* Make certain the data structures used by the LANCE are aligned and DMAble. */
+
lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7,
GFP_DMA | GFP_KERNEL)+7) & ~7);
if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
@@ -483,9 +530,9 @@ __initfunc(void lance_probe1(int ioaddr))
outw(0x0000, ioaddr+LANCE_ADDR);
inw(ioaddr+LANCE_ADDR);
- if (pci_irq_line) {
+ if (irq) { /* Set iff PCI card. */
dev->dma = 4; /* Native bus-master, no DMA channel needed. */
- dev->irq = pci_irq_line;
+ dev->irq = irq;
} else if (hp_builtin) {
static const char dma_tbl[4] = {3, 5, 6, 0};
static const char irq_tbl[4] = {3, 4, 5, 9};
@@ -534,7 +581,7 @@ __initfunc(void lance_probe1(int ioaddr))
printk(", probed IRQ %d", dev->irq);
else {
printk(", failed to detect IRQ line.\n");
- return;
+ return -ENODEV;
}
/* Check for the initialization done bit, 0x0100, which means
@@ -548,7 +595,7 @@ __initfunc(void lance_probe1(int ioaddr))
} else if (dev->dma) {
if (request_dma(dev->dma, chipname)) {
printk("DMA %d allocation failed.\n", dev->dma);
- return;
+ return -ENODEV;
} else
printk(", assigned DMA %d.\n", dev->dma);
} else { /* OK, we have to auto-DMA. */
@@ -588,7 +635,7 @@ __initfunc(void lance_probe1(int ioaddr))
}
if (i == 4) { /* Failure: bail. */
printk("DMA detection failed.\n");
- return;
+ return -ENODEV;
}
}
@@ -601,7 +648,7 @@ __initfunc(void lance_probe1(int ioaddr))
dev->irq = autoirq_report(4);
if (dev->irq == 0) {
printk(" Failed to detect the 7990 IRQ line.\n");
- return;
+ return -ENODEV;
}
printk(" Auto-IRQ detected IRQ%d.\n", dev->irq);
}
@@ -610,8 +657,8 @@ __initfunc(void lance_probe1(int ioaddr))
/* Turn on auto-select of media (10baseT or BNC) so that the user
can watch the LEDs even if the board isn't opened. */
outw(0x0002, ioaddr+LANCE_ADDR);
- /* set autoselect and clean xmausel */
- outw((inw(ioaddr+LANCE_BUS_IF) & 0xfffe) | 0x0002, ioaddr+LANCE_BUS_IF);
+ /* Don't touch 10base2 power bit. */
+ outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
}
if (lance_debug > 0 && did_version++ == 0)
@@ -624,7 +671,7 @@ __initfunc(void lance_probe1(int ioaddr))
dev->get_stats = lance_get_stats;
dev->set_multicast_list = set_multicast_list;
- return;
+ return 0;
}
static int
@@ -647,6 +694,8 @@ lance_open(struct device *dev)
return -EAGAIN;
}
+ MOD_INC_USE_COUNT;
+
/* We used to allocate DMA here, but that was silly.
DMA lines can't be shared! We now permanently allocate them. */
@@ -668,9 +717,9 @@ lance_open(struct device *dev)
if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) {
/* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */
outw(0x0002, ioaddr+LANCE_ADDR);
- /* set autoselect and clean xmausel */
- outw((inw(ioaddr+LANCE_BUS_IF) & 0xfffe) | 0x0002, ioaddr+LANCE_BUS_IF);
- }
+ /* Only touch autoselect bit. */
+ outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
+ }
if (lance_debug > 1)
printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
@@ -679,7 +728,7 @@ lance_open(struct device *dev)
(u32) virt_to_bus(lp->rx_ring),
(u32) virt_to_bus(&lp->init_block));
- lance_init_ring(dev);
+ lance_init_ring(dev, GFP_KERNEL);
/* Re-initialize the LANCE, and start it when done. */
outw(0x0001, ioaddr+LANCE_ADDR);
outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
@@ -741,7 +790,7 @@ lance_purge_tx_ring(struct device *dev)
/* Initialize the LANCE Rx and Tx rings. */
static void
-lance_init_ring(struct device *dev)
+lance_init_ring(struct device *dev, int gfp)
{
struct lance_private *lp = (struct lance_private *)dev->priv;
int i;
@@ -751,12 +800,26 @@ lance_init_ring(struct device *dev)
lp->dirty_rx = lp->dirty_tx = 0;
for (i = 0; i < RX_RING_SIZE; i++) {
- lp->rx_ring[i].base = (u32)virt_to_bus((char *)lp->rx_buffs + i*PKT_BUF_SZ) | 0x80000000;
+ struct sk_buff *skb;
+ void *rx_buff;
+
+ skb = alloc_skb(PKT_BUF_SZ, GFP_DMA | gfp);
+ lp->rx_skbuff[i] = skb;
+ if (skb) {
+ skb->dev = dev;
+ rx_buff = skb->tail;
+ } else
+ rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp);
+ if (rx_buff == NULL)
+ lp->rx_ring[i].base = 0;
+ else
+ lp->rx_ring[i].base = (u32)virt_to_bus(rx_buff) | 0x80000000;
lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
}
/* The Tx buffer address is filled in as needed, but we do need to clear
the upper ownership bit. */
for (i = 0; i < TX_RING_SIZE; i++) {
+ lp->tx_skbuff[i] = 0;
lp->tx_ring[i].base = 0;
}
@@ -777,7 +840,7 @@ lance_restart(struct device *dev, unsigned int csr0_bits, int must_reinit)
if (must_reinit ||
(chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) {
lance_purge_tx_ring(dev);
- lance_init_ring(dev);
+ lance_init_ring(dev, GFP_ATOMIC);
}
outw(0x0000, dev->base_addr + LANCE_ADDR);
outw(csr0_bits, dev->base_addr + LANCE_DATA);
@@ -872,14 +935,14 @@ static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
lp->tx_ring[entry].base =
((u32)virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
- dev_kfree_skb (skb);
+ dev_kfree_skb(skb);
} else {
lp->tx_skbuff[entry] = skb;
lp->tx_ring[entry].base = ((u32)virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
}
lp->cur_tx++;
- lp->stats.tx_bytes+=skb->len;
-
+ lp->stats.tx_bytes += skb->len;
+
/* Trigger an immediate send poll. */
outw(0x0000, ioaddr+LANCE_ADDR);
outw(0x0048, ioaddr+LANCE_DATA);
@@ -915,7 +978,7 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs)
ioaddr = dev->base_addr;
lp = (struct lance_private *)dev->priv;
if (dev->interrupt)
- printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
dev->interrupt = 1;
@@ -1110,6 +1173,7 @@ lance_close(struct device *dev)
{
int ioaddr = dev->base_addr;
struct lance_private *lp = (struct lance_private *)dev->priv;
+ int i;
dev->start = 0;
dev->tbusy = 1;
@@ -1134,9 +1198,23 @@ lance_close(struct device *dev)
disable_dma(dev->dma);
release_dma_lock(flags);
}
-
free_irq(dev->irq, dev);
+ /* Free all the skbuffs in the Rx and Tx queues. */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ struct sk_buff *skb = lp->rx_skbuff[i];
+ lp->rx_skbuff[i] = 0;
+ lp->rx_ring[i].base = 0; /* Not owned by LANCE chip. */
+ if (skb)
+ dev_kfree_skb(skb);
+ }
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ if (lp->tx_skbuff[i])
+ dev_kfree_skb(lp->tx_skbuff[i]);
+ lp->tx_skbuff[i] = 0;
+ }
+
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -1195,11 +1273,3 @@ static void set_multicast_list(struct device *dev)
}
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c lance.c"
- * c-indent-level: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 1d3b02a86..1fa60e04d 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -430,7 +430,6 @@ void cleanup_module(void)
release_region(dev->base_addr, LNE390_IO_EXTENT);
if (ei_status.reg0)
iounmap((void *)dev->mem_start);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/ltpc.c b/drivers/net/ltpc.c
index c90f05945..1ffe0f368 100644
--- a/drivers/net/ltpc.c
+++ b/drivers/net/ltpc.c
@@ -1059,14 +1059,14 @@ __initfunc(int ltpc_probe_dma(int base))
inb_p(io+1);
inb_p(io+0);
- timeout = jiffies+100;
- while(timeout>jiffies) {
+ timeout = jiffies+100*HZ/100;
+ while(time_before(jiffies, timeout)) {
if ( 0xfa == inb_p(io+6) ) break;
}
inb_p(io+3);
inb_p(io+2);
- while(timeout>jiffies) {
+ while(time_before(jiffies, timeout)) {
if ( 0xfb == inb_p(io+6) ) break;
}
@@ -1161,8 +1161,8 @@ __initfunc(int ltpc_probe(struct device *dev))
inb_p(io+1);
inb_p(io+3);
- timeout = jiffies+2;
- while(timeout>jiffies) ; /* hold it in reset for a coupla jiffies */
+ timeout = jiffies+2*HZ/100;
+ while(time_before(jiffies, timeout)) ; /* hold it in reset for a coupla jiffies */
inb_p(io+0);
inb_p(io+2);
inb_p(io+7); /* clear reset */
@@ -1171,9 +1171,9 @@ __initfunc(int ltpc_probe(struct device *dev))
inb_p(io+5); /* enable dma */
inb_p(io+6); /* tri-state interrupt line */
- timeout = jiffies+100;
+ timeout = jiffies+100*HZ/100;
- while(timeout>jiffies) {
+ while(time_before(jiffies, timeout)) {
/* wait for the card to complete initialization */
}
@@ -1220,8 +1220,8 @@ __initfunc(int ltpc_probe(struct device *dev))
(void) inb_p(io+3);
(void) inb_p(io+2);
- timeout = jiffies+100;
- while(timeout>jiffies) {
+ timeout = jiffies+100*HZ/100;
+ while(time_before(jiffies, timeout)) {
if( 0xf9 == inb_p(io+6)) break;
}
@@ -1335,7 +1335,7 @@ void cleanup_module(void)
/* if it's in process, wait a bit for it to finish */
timeout = jiffies+HZ;
add_timer(&ltpc_timer);
- while(del_timer(&ltpc_timer) && (timeout > jiffies))
+ while(del_timer(&ltpc_timer) && time_after(timeout, jiffies))
{
add_timer(&ltpc_timer);
schedule();
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index ab284bf09..36b9123e8 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -68,8 +68,9 @@ static const char *version =
/* A zero-terminated list of I/O addresses to be probed at boot. */
#ifndef MODULE
-static unsigned int netcard_portlist[] __initdata =
-{ 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0};
+static unsigned int netcard_portlist[] __initdata = {
+ 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
+};
#endif
#ifdef CONFIG_PCI
@@ -85,6 +86,8 @@ pci_clone_list[] __initdata = {
{PCI_VENDOR_ID_SURECOM, PCI_DEVICE_ID_SURECOM_NE34, "SureCom NE34"},
{0,}
};
+
+static int probe_pci = 1;
#endif
#ifdef SUPPORT_NE_BAD_CLONES
@@ -175,32 +178,32 @@ struct netdev_entry netcard_drv =
__initfunc(int ne_probe(struct device *dev))
{
- int base_addr = dev ? dev->base_addr : 0;
+ int base_addr = dev ? dev->base_addr : 0;
- /* First check any supplied i/o locations. User knows best. <cough> */
- if (base_addr > 0x1ff) /* Check a single specified location. */
- return ne_probe1(dev, base_addr);
- else if (base_addr != 0) /* Don't probe at all. */
- return ENXIO;
+ /* First check any supplied i/o locations. User knows best. <cough> */
+ if (base_addr > 0x1ff) /* Check a single specified location. */
+ return ne_probe1(dev, base_addr);
+ else if (base_addr != 0) /* Don't probe at all. */
+ return ENXIO;
#ifdef CONFIG_PCI
- /* Then look for any installed PCI clones */
- if (pci_present() && (ne_probe_pci(dev) == 0))
- return 0;
+ /* Then look for any installed PCI clones */
+ if (probe_pci && pci_present() && (ne_probe_pci(dev) == 0))
+ return 0;
#endif
#ifndef MODULE
- /* Last resort. The semi-risky ISA auto-probe. */
- for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
- int ioaddr = netcard_portlist[base_addr];
- if (check_region(ioaddr, NE_IO_EXTENT))
- continue;
- if (ne_probe1(dev, ioaddr) == 0)
- return 0;
- }
+ /* Last resort. The semi-risky ISA auto-probe. */
+ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
+ int ioaddr = netcard_portlist[base_addr];
+ if (check_region(ioaddr, NE_IO_EXTENT))
+ continue;
+ if (ne_probe1(dev, ioaddr) == 0)
+ return 0;
+ }
#endif
- return ENODEV;
+ return ENODEV;
}
#endif
@@ -223,7 +226,7 @@ __initfunc(static int ne_probe_pci(struct device *dev))
}
if (!pdev)
continue;
- printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
+ printk(KERN_INFO "ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
pci_clone_list[i].name,
pci_ioaddr, pci_irq_line);
printk("*\n* Use of the PCI-NE2000 driver with this card is recommended!\n*\n");
@@ -241,61 +244,65 @@ __initfunc(static int ne_probe_pci(struct device *dev))
__initfunc(static int ne_probe1(struct device *dev, int ioaddr))
{
- int i;
- unsigned char SA_prom[32];
- int wordlength = 2;
- const char *name = NULL;
- int start_page, stop_page;
- int neX000, ctron, bad_card;
- int reg0 = inb_p(ioaddr);
- static unsigned version_printed = 0;
-
- if (reg0 == 0xFF)
- return ENODEV;
-
- /* Do a preliminary verification that we have a 8390. */
- { int regd;
- outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
- regd = inb_p(ioaddr + 0x0d);
- outb_p(0xff, ioaddr + 0x0d);
- outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
- inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
- if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
- outb_p(reg0, ioaddr);
- outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */
- return ENODEV;
+ int i;
+ unsigned char SA_prom[32];
+ int wordlength = 2;
+ const char *name = NULL;
+ int start_page, stop_page;
+ int neX000, ctron, copam, bad_card;
+ int reg0 = inb_p(ioaddr);
+ static unsigned version_printed = 0;
+
+ if (reg0 == 0xFF)
+ return ENODEV;
+
+ /* Do a preliminary verification that we have a 8390. */
+ {
+ int regd;
+ outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+ regd = inb_p(ioaddr + 0x0d);
+ outb_p(0xff, ioaddr + 0x0d);
+ outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+ inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+ if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+ outb_p(reg0, ioaddr);
+ outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */
+ return ENODEV;
+ }
}
- }
- if (load_8390_module("ne.c"))
- return -ENOSYS;
+ if (load_8390_module("ne.c"))
+ return -ENOSYS;
+
+ /* We should have a "dev" from Space.c or the static module table. */
+ if (dev == NULL)
+ {
+ printk(KERN_ERR "ne.c: Passed a NULL device.\n");
+ dev = init_etherdev(0, 0);
+ }
- /* We should have a "dev" from Space.c or the static module table. */
- if (dev == NULL) {
- printk(KERN_ERR "ne.c: Passed a NULL device.\n");
- dev = init_etherdev(0, 0);
- }
+ if (ei_debug && version_printed++ == 0)
+ printk(version);
- if (ei_debug && version_printed++ == 0)
- printk(version);
+ printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
- printk("NE*000 ethercard probe at %#3x:", ioaddr);
+ /* A user with a poor card that fails to ack the reset, or that
+ does not have a valid 0x57,0x57 signature can still use this
+ without having to recompile. Specifying an i/o address along
+ with an otherwise unused dev->mem_end value of "0xBAD" will
+ cause the driver to skip these parts of the probe. */
- /* A user with a poor card that fails to ack the reset, or that
- does not have a valid 0x57,0x57 signature can still use this
- without having to recompile. Specifying an i/o address along
- with an otherwise unused dev->mem_end value of "0xBAD" will
- cause the driver to skip these parts of the probe. */
+ bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
- bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+ /* Reset card. Who knows what dain-bramaged state it was left in. */
- /* Reset card. Who knows what dain-bramaged state it was left in. */
- { unsigned long reset_start_time = jiffies;
+ {
+ unsigned long reset_start_time = jiffies;
- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
- outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+ /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+ outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
- while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+ while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
if (jiffies - reset_start_time > 2*HZ/100) {
if (bad_card) {
printk(" (warning: no reset ack)");
@@ -305,252 +312,265 @@ __initfunc(static int ne_probe1(struct device *dev, int ioaddr))
return ENODEV;
}
}
+
+ outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */
+ }
+
+ /* Read the 16 bytes of station address PROM.
+ We must first initialize registers, similar to NS8390_init(eifdev, 0).
+ We can't reliably read the SAPROM address without this.
+ (I learned the hard way!). */
+ {
+ struct {unsigned char value, offset; } program_seq[] =
+ {
+ {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+ {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
+ {0x00, EN0_RCNTLO}, /* Clear the count regs. */
+ {0x00, EN0_RCNTHI},
+ {0x00, EN0_IMR}, /* Mask completion irq. */
+ {0xFF, EN0_ISR},
+ {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
+ {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
+ {32, EN0_RCNTLO},
+ {0x00, EN0_RCNTHI},
+ {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
+ {0x00, EN0_RSARHI},
+ {E8390_RREAD+E8390_START, E8390_CMD},
+ };
+
+ for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
+ outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
- outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */
- }
-
- /* Read the 16 bytes of station address PROM.
- We must first initialize registers, similar to NS8390_init(eifdev, 0).
- We can't reliably read the SAPROM address without this.
- (I learned the hard way!). */
- {
- struct {unsigned char value, offset; } program_seq[] = {
- {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
- {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
- {0x00, EN0_RCNTLO}, /* Clear the count regs. */
- {0x00, EN0_RCNTHI},
- {0x00, EN0_IMR}, /* Mask completion irq. */
- {0xFF, EN0_ISR},
- {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
- {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
- {32, EN0_RCNTLO},
- {0x00, EN0_RCNTHI},
- {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
- {0x00, EN0_RSARHI},
- {E8390_RREAD+E8390_START, E8390_CMD},
- };
- for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
- outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
- }
- for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
- SA_prom[i] = inb(ioaddr + NE_DATAPORT);
- SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
- if (SA_prom[i] != SA_prom[i+1])
- wordlength = 1;
- }
-
- /* At this point, wordlength *only* tells us if the SA_prom is doubled
- up or not because some broken PCI cards don't respect the byte-wide
- request in program_seq above, and hence don't have doubled up values.
- These broken cards would otherwise be detected as an ne1000. */
-
- if (wordlength == 2)
- for (i = 0; i < 16; i++)
- SA_prom[i] = SA_prom[i+i];
-
- if (pci_irq_line || ioaddr >= 0x400)
- wordlength = 2; /* Catch broken PCI cards mentioned above. */
-
- if (wordlength == 2) {
- /* We must set the 8390 for word mode. */
- outb_p(0x49, ioaddr + EN0_DCFG);
- start_page = NESM_START_PG;
- stop_page = NESM_STOP_PG;
- } else {
- start_page = NE1SM_START_PG;
- stop_page = NE1SM_STOP_PG;
- }
-
- neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
- ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-
- /* Set up the rest of the parameters. */
- if (neX000 || bad_card) {
- name = (wordlength == 2) ? "NE2000" : "NE1000";
- } else if (ctron) {
- name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
- start_page = 0x01;
- stop_page = (wordlength == 2) ? 0x40 : 0x20;
- } else {
-#ifdef SUPPORT_NE_BAD_CLONES
- /* Ack! Well, there might be a *bad* NE*000 clone there.
- Check for total bogus addresses. */
- for (i = 0; bad_clone_list[i].name8; i++) {
- if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
- SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
- SA_prom[2] == bad_clone_list[i].SAprefix[2]) {
- if (wordlength == 2) {
- name = bad_clone_list[i].name16;
- } else {
- name = bad_clone_list[i].name8;
- }
- break;
- }
}
- if (bad_clone_list[i].name8 == NULL) {
- printk(" not found (invalid signature %2.2x %2.2x).\n",
- SA_prom[14], SA_prom[15]);
- return ENXIO;
+ for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+ SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+ SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+ if (SA_prom[i] != SA_prom[i+1])
+ wordlength = 1;
}
+
+ /* At this point, wordlength *only* tells us if the SA_prom is doubled
+ up or not because some broken PCI cards don't respect the byte-wide
+ request in program_seq above, and hence don't have doubled up values.
+ These broken cards would otherwise be detected as an ne1000. */
+
+ if (wordlength == 2)
+ for (i = 0; i < 16; i++)
+ SA_prom[i] = SA_prom[i+i];
+
+ if (pci_irq_line || ioaddr >= 0x400)
+ wordlength = 2; /* Catch broken PCI cards mentioned above. */
+
+ if (wordlength == 2)
+ {
+ /* We must set the 8390 for word mode. */
+ outb_p(0x49, ioaddr + EN0_DCFG);
+ start_page = NESM_START_PG;
+ stop_page = NESM_STOP_PG;
+ } else {
+ start_page = NE1SM_START_PG;
+ stop_page = NE1SM_STOP_PG;
+ }
+
+ neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57);
+ ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+ copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
+
+
+ /* Set up the rest of the parameters. */
+ if (neX000 || bad_card || copam) {
+ name = (wordlength == 2) ? "NE2000" : "NE1000";
+ }
+ else if (ctron)
+ {
+ name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+ start_page = 0x01;
+ stop_page = (wordlength == 2) ? 0x40 : 0x20;
+ }
+ else
+ {
+#ifdef SUPPORT_NE_BAD_CLONES
+ /* Ack! Well, there might be a *bad* NE*000 clone there.
+ Check for total bogus addresses. */
+ for (i = 0; bad_clone_list[i].name8; i++)
+ {
+ if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+ SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+ SA_prom[2] == bad_clone_list[i].SAprefix[2])
+ {
+ if (wordlength == 2)
+ {
+ name = bad_clone_list[i].name16;
+ } else {
+ name = bad_clone_list[i].name8;
+ }
+ break;
+ }
+ }
+ if (bad_clone_list[i].name8 == NULL)
+ {
+ printk(" not found (invalid signature %2.2x %2.2x).\n",
+ SA_prom[14], SA_prom[15]);
+ return ENXIO;
+ }
#else
- printk(" not found.\n");
- return ENXIO;
+ printk(" not found.\n");
+ return ENXIO;
#endif
+ }
- }
-
- if (pci_irq_line)
- dev->irq = pci_irq_line;
-
- if (dev->irq < 2) {
- autoirq_setup(0);
- outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
- outb_p(0x00, ioaddr + EN0_RCNTLO);
- outb_p(0x00, ioaddr + EN0_RCNTHI);
- outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
- mdelay(10); /* wait 10ms for interrupt to propagate */
- outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
- dev->irq = autoirq_report(0);
- if (ei_debug > 2)
- printk(" autoirq is %d\n", dev->irq);
- } else if (dev->irq == 2)
- /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
- or don't know which one to set. */
- dev->irq = 9;
-
- if (! dev->irq) {
- printk(" failed to detect IRQ line.\n");
- return EAGAIN;
- }
-
- /* Allocate dev->priv and fill in 8390 specific dev fields. */
- if (ethdev_init(dev)) {
- printk (" unable to get memory for dev->priv.\n");
- return -ENOMEM;
- }
+ if (pci_irq_line)
+ dev->irq = pci_irq_line;
+
+ if (dev->irq < 2)
+ {
+ autoirq_setup(0);
+ outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
+ outb_p(0x00, ioaddr + EN0_RCNTLO);
+ outb_p(0x00, ioaddr + EN0_RCNTHI);
+ outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
+ mdelay(10); /* wait 10ms for interrupt to propagate */
+ outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */
+ dev->irq = autoirq_report(0);
+ if (ei_debug > 2)
+ printk(" autoirq is %d\n", dev->irq);
+ } else if (dev->irq == 2)
+ /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
+ or don't know which one to set. */
+ dev->irq = 9;
+
+ if (! dev->irq) {
+ printk(" failed to detect IRQ line.\n");
+ return EAGAIN;
+ }
+
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev))
+ {
+ printk (" unable to get memory for dev->priv.\n");
+ return -ENOMEM;
+ }
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share and the board will usually be enabled. */
- {
- int irqval = request_irq(dev->irq, ei_interrupt,
- pci_irq_line ? SA_SHIRQ : 0, name, dev);
- if (irqval) {
- printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
+ /* Snarf the interrupt now. There's no point in waiting since we cannot
+ share and the board will usually be enabled. */
- kfree(dev->priv);
- dev->priv = NULL;
- return EAGAIN;
+ {
+ int irqval = request_irq(dev->irq, ei_interrupt,
+ pci_irq_line ? SA_SHIRQ : 0, name, dev);
+ if (irqval) {
+ printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
+ kfree(dev->priv);
+ dev->priv = NULL;
+ return EAGAIN;
+ }
}
- }
- dev->base_addr = ioaddr;
- request_region(ioaddr, NE_IO_EXTENT, name);
+ dev->base_addr = ioaddr;
+ request_region(ioaddr, NE_IO_EXTENT, name);
- for(i = 0; i < ETHER_ADDR_LEN; i++) {
- printk(" %2.2x", SA_prom[i]);
- dev->dev_addr[i] = SA_prom[i];
- }
+ for(i = 0; i < ETHER_ADDR_LEN; i++) {
+ printk(" %2.2x", SA_prom[i]);
+ dev->dev_addr[i] = SA_prom[i];
+ }
- printk("\n%s: %s found at %#x, using IRQ %d.\n",
- dev->name, name, ioaddr, dev->irq);
+ printk("\n%s: %s found at %#x, using IRQ %d.\n",
+ dev->name, name, ioaddr, dev->irq);
- ei_status.name = name;
- ei_status.tx_start_page = start_page;
- ei_status.stop_page = stop_page;
- ei_status.word16 = (wordlength == 2);
+ ei_status.name = name;
+ ei_status.tx_start_page = start_page;
+ ei_status.stop_page = stop_page;
+ ei_status.word16 = (wordlength == 2);
- ei_status.rx_start_page = start_page + TX_PAGES;
+ ei_status.rx_start_page = start_page + TX_PAGES;
#ifdef PACKETBUF_MEMSIZE
- /* Allow the packet buffer size to be overridden by know-it-alls. */
- ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+ /* Allow the packet buffer size to be overridden by know-it-alls. */
+ ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
#endif
- ei_status.reset_8390 = &ne_reset_8390;
- ei_status.block_input = &ne_block_input;
- ei_status.block_output = &ne_block_output;
- ei_status.get_8390_hdr = &ne_get_8390_hdr;
- dev->open = &ne_open;
- dev->stop = &ne_close;
- NS8390_init(dev, 0);
- return 0;
+ ei_status.reset_8390 = &ne_reset_8390;
+ ei_status.block_input = &ne_block_input;
+ ei_status.block_output = &ne_block_output;
+ ei_status.get_8390_hdr = &ne_get_8390_hdr;
+ dev->open = &ne_open;
+ dev->stop = &ne_close;
+ NS8390_init(dev, 0);
+ return 0;
}
-static int
-ne_open(struct device *dev)
+static int ne_open(struct device *dev)
{
- ei_open(dev);
- MOD_INC_USE_COUNT;
- return 0;
+ ei_open(dev);
+ MOD_INC_USE_COUNT;
+ return 0;
}
-static int
-ne_close(struct device *dev)
+static int ne_close(struct device *dev)
{
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
- ei_close(dev);
- MOD_DEC_USE_COUNT;
- return 0;
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+ ei_close(dev);
+ MOD_DEC_USE_COUNT;
+ return 0;
}
/* Hard reset the card. This used to pause for the same period that a
8390 reset command required, but that shouldn't be necessary. */
-static void
-ne_reset_8390(struct device *dev)
+
+static void ne_reset_8390(struct device *dev)
{
- unsigned long reset_start_time = jiffies;
+ unsigned long reset_start_time = jiffies;
- if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
+ if (ei_debug > 1)
+ printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
- /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
- outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+ /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+ outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
- ei_status.txing = 0;
- ei_status.dmaing = 0;
+ ei_status.txing = 0;
+ ei_status.dmaing = 0;
- /* This check _should_not_ be necessary, omit eventually. */
- while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
- if (jiffies - reset_start_time > 2*HZ/100) {
- printk("%s: ne_reset_8390() did not complete.\n", dev->name);
- break;
- }
- outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
+ /* This check _should_not_ be necessary, omit eventually. */
+ while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+ if (jiffies - reset_start_time > 2*HZ/100) {
+ printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+ break;
+ }
+ outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
}
/* Grab the 8390 specific header. Similar to the block_input routine, but
we don't need to be concerned with ring wrap as the header will be at
the start of a page, so we optimize accordingly. */
-static void
-ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
+ int nic_base = dev->base_addr;
- int nic_base = dev->base_addr;
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk("%s: DMAing conflict in ne_get_8390_hdr "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
- return;
- }
-
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
- outb_p(0, nic_base + EN0_RCNTHI);
- outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
- outb_p(ring_page, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
- if (ei_status.word16)
- insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
- else
- insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
+ if (ei_status.dmaing)
+ {
+ printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+ "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock,
+ dev->interrupt);
+ return;
+ }
+
+ ei_status.dmaing |= 0x01;
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+ outb_p(0, nic_base + EN0_RCNTHI);
+ outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
+ outb_p(ring_page, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+ if (ei_status.word16)
+ insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+ else
+ insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
}
/* Block input and output, similar to the Crynwr packet driver. If you
@@ -558,164 +578,176 @@ ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
The NEx000 doesn't share the on-board packet memory -- you have to put
the packet out through the "remote DMA" dataport using outb. */
-static void
-ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
{
#ifdef NE_SANITY_CHECK
- int xfer_count = count;
+ int xfer_count = count;
#endif
- int nic_base = dev->base_addr;
- char *buf = skb->data;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk("%s: DMAing conflict in ne_block_input "
- "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
- return;
- }
- ei_status.dmaing |= 0x01;
- outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
- outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- insw(NE_BASE + NE_DATAPORT,buf,count>>1);
- if (count & 0x01) {
- buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+ int nic_base = dev->base_addr;
+ char *buf = skb->data;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing)
+ {
+ printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+ "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock,
+ dev->interrupt);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+ outb_p(count >> 8, nic_base + EN0_RCNTHI);
+ outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+ outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ if (ei_status.word16)
+ {
+ insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+ if (count & 0x01)
+ {
+ buf[count-1] = inb(NE_BASE + NE_DATAPORT);
#ifdef NE_SANITY_CHECK
- xfer_count++;
+ xfer_count++;
#endif
- }
- } else {
- insb(NE_BASE + NE_DATAPORT, buf, count);
- }
+ }
+ } else {
+ insb(NE_BASE + NE_DATAPORT, buf, count);
+ }
#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. If you see
- this message you either 1) have a slightly incompatible clone
- or 2) have noise/speed problems with your bus. */
- if (ei_debug > 1) { /* DMA termination address check... */
- int addr, tries = 20;
- do {
- /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
- -- it's broken for Rx on some cards! */
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if (((ring_offset + xfer_count) & 0xff) == low)
- break;
- } while (--tries > 0);
- if (tries <= 0)
- printk("%s: RX transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, ring_offset + xfer_count, addr);
- }
+ /* This was for the ALPHA version only, but enough people have
+ been encountering problems so it is still here. If you see
+ this message you either 1) have a slightly incompatible clone
+ or 2) have noise/speed problems with your bus. */
+
+ if (ei_debug > 1)
+ {
+ /* DMA termination address check... */
+ int addr, tries = 20;
+ do {
+ /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+ -- it's broken for Rx on some cards! */
+ int high = inb_p(nic_base + EN0_RSARHI);
+ int low = inb_p(nic_base + EN0_RSARLO);
+ addr = (high << 8) + low;
+ if (((ring_offset + xfer_count) & 0xff) == low)
+ break;
+ } while (--tries > 0);
+ if (tries <= 0)
+ printk(KERN_WARNING "%s: RX transfer address mismatch,"
+ "%#4.4x (expected) vs. %#4.4x (actual).\n",
+ dev->name, ring_offset + xfer_count, addr);
+ }
#endif
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
+ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
}
-static void
-ne_block_output(struct device *dev, int count,
+static void ne_block_output(struct device *dev, int count,
const unsigned char *buf, const int start_page)
{
- int nic_base = NE_BASE;
- unsigned long dma_start;
+ int nic_base = NE_BASE;
+ unsigned long dma_start;
#ifdef NE_SANITY_CHECK
- int retries = 0;
+ int retries = 0;
#endif
- /* Round the count up for word writes. Do we need to do this?
- What effect will an odd byte count have on the 8390?
- I should check someday. */
- if (ei_status.word16 && (count & 0x01))
- count++;
-
- /* This *shouldn't* happen. If it does, it's the last thing you'll see */
- if (ei_status.dmaing) {
- printk("%s: DMAing conflict in ne_block_output."
- "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
- dev->name, ei_status.dmaing, ei_status.irqlock,
- dev->interrupt);
- return;
- }
- ei_status.dmaing |= 0x01;
- /* We should already be in page 0, but to be safe... */
- outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+ /* Round the count up for word writes. Do we need to do this?
+ What effect will an odd byte count have on the 8390?
+ I should check someday. */
+
+ if (ei_status.word16 && (count & 0x01))
+ count++;
+
+ /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ if (ei_status.dmaing)
+ {
+ printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+ "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
+ dev->name, ei_status.dmaing, ei_status.irqlock,
+ dev->interrupt);
+ return;
+ }
+ ei_status.dmaing |= 0x01;
+ /* We should already be in page 0, but to be safe... */
+ outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
#ifdef NE_SANITY_CHECK
- retry:
+retry:
#endif
#ifdef NE8390_RW_BUGFIX
- /* Handle the read-before-write bug the same way as the
- Crynwr packet driver -- the NatSemi method doesn't work.
- Actually this doesn't always work either, but if you have
- problems with your NEx000 this is better than nothing! */
- outb_p(0x42, nic_base + EN0_RCNTLO);
- outb_p(0x00, nic_base + EN0_RCNTHI);
- outb_p(0x42, nic_base + EN0_RSARLO);
- outb_p(0x00, nic_base + EN0_RSARHI);
- outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
- /* Make certain that the dummy read has occurred. */
- udelay(6);
+ /* Handle the read-before-write bug the same way as the
+ Crynwr packet driver -- the NatSemi method doesn't work.
+ Actually this doesn't always work either, but if you have
+ problems with your NEx000 this is better than nothing! */
+
+ outb_p(0x42, nic_base + EN0_RCNTLO);
+ outb_p(0x00, nic_base + EN0_RCNTHI);
+ outb_p(0x42, nic_base + EN0_RSARLO);
+ outb_p(0x00, nic_base + EN0_RSARHI);
+ outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+ /* Make certain that the dummy read has occurred. */
+ udelay(6);
#endif
- outb_p(ENISR_RDC, nic_base + EN0_ISR);
+ outb_p(ENISR_RDC, nic_base + EN0_ISR);
- /* Now the normal output. */
- outb_p(count & 0xff, nic_base + EN0_RCNTLO);
- outb_p(count >> 8, nic_base + EN0_RCNTHI);
- outb_p(0x00, nic_base + EN0_RSARLO);
- outb_p(start_page, nic_base + EN0_RSARHI);
+ /* Now the normal output. */
+ outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+ outb_p(count >> 8, nic_base + EN0_RCNTHI);
+ outb_p(0x00, nic_base + EN0_RSARLO);
+ outb_p(start_page, nic_base + EN0_RSARHI);
- outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
- if (ei_status.word16) {
- outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
- } else {
- outsb(NE_BASE + NE_DATAPORT, buf, count);
- }
+ outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+ if (ei_status.word16) {
+ outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+ } else {
+ outsb(NE_BASE + NE_DATAPORT, buf, count);
+ }
- dma_start = jiffies;
+ dma_start = jiffies;
#ifdef NE_SANITY_CHECK
- /* This was for the ALPHA version only, but enough people have
- been encountering problems so it is still here. */
- if (ei_debug > 1) { /* DMA termination address check... */
- int addr, tries = 20;
- do {
- int high = inb_p(nic_base + EN0_RSARHI);
- int low = inb_p(nic_base + EN0_RSARLO);
- addr = (high << 8) + low;
- if ((start_page << 8) + count == addr)
- break;
- } while (--tries > 0);
- if (tries <= 0) {
- printk("%s: Tx packet transfer address mismatch,"
- "%#4.4x (expected) vs. %#4.4x (actual).\n",
- dev->name, (start_page << 8) + count, addr);
- if (retries++ == 0)
- goto retry;
+ /* This was for the ALPHA version only, but enough people have
+ been encountering problems so it is still here. */
+
+ if (ei_debug > 1)
+ {
+ /* DMA termination address check... */
+ int addr, tries = 20;
+ do {
+ int high = inb_p(nic_base + EN0_RSARHI);
+ int low = inb_p(nic_base + EN0_RSARLO);
+ addr = (high << 8) + low;
+ if ((start_page << 8) + count == addr)
+ break;
+ } while (--tries > 0);
+
+ if (tries <= 0)
+ {
+ printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+ "%#4.4x (expected) vs. %#4.4x (actual).\n",
+ dev->name, (start_page << 8) + count, addr);
+ if (retries++ == 0)
+ goto retry;
+ }
}
- }
#endif
- while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
- if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
- printk("%s: timeout waiting for Tx RDC.\n", dev->name);
- ne_reset_8390(dev);
- NS8390_init(dev,1);
- break;
- }
+ while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+ if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
+ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+ ne_reset_8390(dev);
+ NS8390_init(dev,1);
+ break;
+ }
- outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
- ei_status.dmaing &= ~0x01;
- return;
+ outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+ ei_status.dmaing &= ~0x01;
+ return;
}
@@ -740,13 +772,16 @@ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
+#ifdef CONFIG_PCI
+MODULE_PARM(probe_pci, "i");
+#endif
+
/* This is set up so that no ISA autoprobe takes place. We can't guarantee
that the ne2k probe is the last 8390 based probe to take place (as it
is at boot) and so the probe will get confused by any other 8390 cards.
ISA device autoprobes on a running machine are not recommended anyway. */
-int
-init_module(void)
+int init_module(void)
{
int this_dev, found = 0;
@@ -775,8 +810,7 @@ init_module(void)
return 0;
}
-void
-cleanup_module(void)
+void cleanup_module(void)
{
int this_dev;
@@ -786,7 +820,6 @@ cleanup_module(void)
void *priv = dev->priv;
free_irq(dev->irq, dev);
release_region(dev->base_addr, NE_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 429699c34..60a729f24 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -43,6 +43,9 @@
- Added code that unregisters irq and proc-info
- Version# bump
+ Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
+ - pass 'dev' as last parameter of request_irq in stead of 'NULL'
+
* WARNING
-------
This is alpha-test software. It is not guaranteed to work. As a
@@ -51,8 +54,7 @@
If it doesn't work, be sure to send me a mail with the problems !
*/
-static const char *version =
-"ne2.c:v0.90 Oct 14 1998 David Weinehall <tao@acc.umu.se>\n";
+static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
#include <linux/module.h>
#include <linux/version.h>
@@ -317,7 +319,7 @@ __initfunc (static int ne2_probe1(struct device *dev, int slot))
share and the board will usually be enabled. */
{
int irqval = request_irq(dev->irq, ei_interrupt,
- 0, name, NULL);
+ 0, name, dev);
if (irqval) {
printk (" unable to get IRQ %d (irqval=%d).\n",
dev->irq, +irqval);
@@ -330,7 +332,7 @@ __initfunc (static int ne2_probe1(struct device *dev, int slot))
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (" unable to get memory for dev->priv.\n");
- free_irq(dev->irq, NULL);
+ free_irq(dev->irq, dev);
return -ENOMEM;
}
@@ -677,10 +679,7 @@ void cleanup_module(void)
mca_mark_as_unused(ei_status.priv);
mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
kfree(dev->priv);
- dev->priv = NULL;
free_irq(dev->irq, dev);
- /* removed (temporary) fot */
- /* irq2dev_map[dev->irq] = NULL; */
release_region(dev->base_addr, NE_IO_EXTENT);
unregister_netdev(dev);
}
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index 8f152673c..1b48abd36 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -70,6 +70,7 @@ pci_clone_list[] __initdata = {
{0x4a14, 0x5000, "NetVin NV5000SC"},
{0x1106, 0x0926, "Via 82C926"},
{0x10bd, 0x0e34, "SureCom NE34"},
+ {0x1050, 0x5a5a, "Winbond"},
{0,}
};
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index d5764928a..eb3098095 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -421,7 +421,6 @@ void cleanup_module(void)
release_region(dev->base_addr, NE3210_IO_EXTENT);
if (ei_status.reg0)
iounmap((void *)dev->mem_start);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/net_init.c b/drivers/net/net_init.c
index 5e381d985..edb41febb 100644
--- a/drivers/net/net_init.c
+++ b/drivers/net/net_init.c
@@ -165,6 +165,9 @@ static int fddi_change_mtu(struct device *dev, int new_mtu)
#endif
#ifdef CONFIG_HIPPI
+#define MAX_HIP_CARDS 4
+static struct device *hipdev_index[MAX_HIP_CARDS];
+
static int hippi_change_mtu(struct device *dev, int new_mtu)
{
/*
@@ -193,32 +196,60 @@ static int hippi_mac_addr(struct device *dev, void *p)
struct device *init_hippi_dev(struct device *dev, int sizeof_priv)
{
- struct device *tmp_dev; /* pointer to a device structure */
+ int new_device = 0;
+ int i;
- /* Find next free HIPPI entry */
+ /* Use an existing correctly named device in Space.c:dev_base. */
+ if (dev == NULL) {
+ int alloc_size = sizeof(struct device) + sizeof("hip%d ")
+ + sizeof_priv + 3;
+ struct device *cur_dev;
+ char pname[8];
- for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next)
- if ((strncmp(tmp_dev->name, "hip", 3) == 0) &&
- (tmp_dev->base_addr == 0))
- break;
+ for (i = 0; i < MAX_HIP_CARDS; ++i)
+ if (hipdev_index[i] == NULL) {
+ sprintf(pname, "hip%d", i);
+ for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
+ if (strcmp(pname, cur_dev->name) == 0) {
+ dev = cur_dev;
+ dev->init = NULL;
+ sizeof_priv = (sizeof_priv + 3) & ~3;
+ dev->priv = sizeof_priv
+ ? kmalloc(sizeof_priv, GFP_KERNEL)
+ : NULL;
+ if (dev->priv) memset(dev->priv, 0, sizeof_priv);
+ goto hipfound;
+ }
+ }
- if (tmp_dev == NULL)
- {
- printk("Could not find free HIPPI device structure.\n");
- return NULL;
+ alloc_size &= ~3; /* Round to dword boundary. */
+
+ dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+ memset(dev, 0, alloc_size);
+ if (sizeof_priv)
+ dev->priv = (void *) (dev + 1);
+ dev->name = sizeof_priv + (char *)(dev + 1);
+ new_device = 1;
}
-
- tmp_dev->init = NULL;
- sizeof_priv = (sizeof_priv + 3) & ~3;
- tmp_dev->priv = sizeof_priv ? kmalloc(sizeof_priv, GFP_KERNEL) : NULL;
- if (tmp_dev->priv)
- memset(dev->priv, 0, sizeof_priv);
+hipfound: /* From the double loop above. */
- /* Initialize remaining device structure information */
+ if (dev->name &&
+ ((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
+ for (i = 0; i < MAX_HIP_CARDS; ++i)
+ if (hipdev_index[i] == NULL) {
+ sprintf(dev->name, "hip%d", i);
+ hipdev_index[i] = dev;
+ break;
+ }
+ }
- hippi_setup(tmp_dev);
- return tmp_dev;
+ hippi_setup(dev);
+
+ if (new_device)
+ register_netdevice(dev);
+
+ return dev;
}
static int hippi_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
@@ -312,6 +343,19 @@ void fddi_setup(struct device *dev)
#ifdef CONFIG_HIPPI
void hippi_setup(struct device *dev)
{
+ int i;
+
+ if (dev->name && (strncmp(dev->name, "hip", 3) == 0)) {
+ i = simple_strtoul(dev->name + 3, NULL, 0);
+ if (hipdev_index[i] == NULL) {
+ hipdev_index[i] = dev;
+ }
+ else if (dev != hipdev_index[i]) {
+ printk("hippi_setup: Ouch! Someone else took %s\n",
+ dev->name);
+ }
+ }
+
dev->set_multicast_list = NULL;
dev->change_mtu = hippi_change_mtu;
dev->hard_header = hippi_header;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index a80d460d0..0e3b0c109 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1,6 +1,6 @@
/* pcnet32.c: An AMD PCnet32 ethernet driver for linux. */
/*
- * Copyright 1996,97,98 Thomas Bogendoerfer
+ * Copyright 1996-1999 Thomas Bogendoerfer
*
* Derived from the lance driver written 1993,1994,1995 by Donald Becker.
*
@@ -13,7 +13,7 @@
* This driver is for PCnet32 and PCnetPCI based ethercards
*/
-static const char *version = "pcnet32.c:v1.02 3.9.98 tsbogend@alpha.franken.de\n";
+static const char *version = "pcnet32.c:v1.11 17.1.99 tsbogend@alpha.franken.de\n";
#include <linux/config.h>
#include <linux/module.h>
@@ -56,6 +56,17 @@ static struct device *pcnet32_dev = NULL;
static const int max_interrupt_work = 20;
static const int rx_copybreak = 200;
+#define PORT_AUI 0x00
+#define PORT_10BT 0x01
+#define PORT_GPSI 0x02
+#define PORT_MII 0x03
+
+#define PORT_PORTSEL 0x03
+#define PORT_ASEL 0x04
+#define PORT_FD 0x80
+
+static int options = PORT_ASEL; /* port selection */
+
/*
* Theory of Operation
*
@@ -106,6 +117,10 @@ static const int rx_copybreak = 200;
* v1.01: do ring dumps, only when debugging the driver
* increased the transmit timeout
* v1.02: fixed memory leak in pcnet32_init_ring()
+ * v1.10: workaround for stopped transmitter
+ * added port selection for modules
+ * detect special T1/E1 WAN card and setup port selection
+ * v1.11: fixed wrong checking of Tx errors
*/
@@ -181,8 +196,9 @@ struct pcnet32_private {
int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
struct net_device_stats stats;
char tx_full;
- unsigned long lock;
- char shared_irq; /* shared irq possible */
+ int options;
+ int shared_irq:1, /* shared irq possible */
+ full_duplex:1; /* full duplex possible */
#ifdef MODULE
struct device *next;
#endif
@@ -260,11 +276,13 @@ __initfunc(int pcnet32_probe (struct device *dev))
unsigned int ioaddr = *port;
if ( check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0) {
- if (pcnet32_probe1(dev, ioaddr, 0, 0) == 0)
+ /* check if there is really a pcnet chip on that ioaddr */
+ if ((inb(ioaddr + 14) == 0x57) &&
+ (inb(ioaddr + 15) == 0x57) &&
+ (pcnet32_probe1(dev, ioaddr, 0, 0) == 0))
return 0;
}
}
-
return ENODEV;
}
@@ -273,13 +291,9 @@ __initfunc(int pcnet32_probe (struct device *dev))
__initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared))
{
struct pcnet32_private *lp;
- int i;
+ int i,full_duplex = 0;
char *chipname;
- /* check if there is really a pcnet chip on that ioaddr */
- if ((inb(ioaddr + 14) != 0x57) || (inb(ioaddr + 15) != 0x57))
- return ENODEV;
-
inw(ioaddr+PCNET32_RESET); /* Reset the PCNET32 */
outw(0x0000, ioaddr+PCNET32_ADDR); /* Switch to window 0 */
@@ -305,16 +319,22 @@ __initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, un
chipname = "PCnet/PCI 79C970";
break;
case 0x2430:
- chipname = "PCnet32";
+ if (shared)
+ chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */
+ else
+ chipname = "PCnet/32 79C965";
break;
case 0x2621:
chipname = "PCnet/PCI II 79C970A";
+ full_duplex = 1;
break;
case 0x2623:
chipname = "PCnet/FAST 79C971";
+ full_duplex = 1;
break;
case 0x2624:
chipname = "PCnet/FAST+ 79C972";
+ full_duplex = 1;
break;
default:
printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version);
@@ -352,8 +372,14 @@ __initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, un
dev->priv = lp;
lp->name = chipname;
lp->shared_irq = shared;
+ lp->full_duplex = full_duplex;
+ lp->options = options;
+
+ /* detect special T1/E1 WAN card by checking for MAC address */
+ if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75)
+ lp->options = PORT_FD | PORT_GPSI;
- lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
+ lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
for (i = 0; i < 6; i++)
lp->init_block.phys_addr[i] = dev->dev_addr[i];
@@ -402,11 +428,6 @@ __initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, un
}
}
- outw(0x0002, ioaddr+PCNET32_ADDR);
- /* only touch autoselect bit */
- outw(inw(ioaddr+PCNET32_BUS_IF) | 0x0002, ioaddr+PCNET32_BUS_IF);
-
-
if (pcnet32_debug > 0)
printk(version);
@@ -433,6 +454,7 @@ pcnet32_open(struct device *dev)
{
struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
unsigned int ioaddr = dev->base_addr;
+ unsigned short val;
int i;
if (dev->irq == 0 ||
@@ -448,19 +470,40 @@ pcnet32_open(struct device *dev)
outw(0x0014, ioaddr+PCNET32_ADDR);
outw(0x0002, ioaddr+PCNET32_BUS_IF);
- /* Turn on auto-select of media (AUI, BNC). */
- outw(0x0002, ioaddr+PCNET32_ADDR);
- /* only touch autoselect bit */
- outw(inw(ioaddr+PCNET32_BUS_IF) | 0x0002, ioaddr+PCNET32_BUS_IF);
-
if (pcnet32_debug > 1)
printk("%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",
dev->name, dev->irq,
(u32) virt_to_bus(lp->tx_ring),
(u32) virt_to_bus(lp->rx_ring),
(u32) virt_to_bus(&lp->init_block));
-
- lp->init_block.mode = 0x0000;
+
+ /* set/reset autoselect bit */
+ outw(0x0002, ioaddr+PCNET32_ADDR);
+ val = inw(ioaddr+PCNET32_BUS_IF) & ~2;
+ if (lp->options & PORT_ASEL)
+ val |= 2;
+ outw(val, ioaddr+PCNET32_BUS_IF);
+
+ /* handle full duplex setting */
+ if (lp->full_duplex) {
+ outw (0x0009, ioaddr+PCNET32_ADDR);
+ val = inw(ioaddr+PCNET32_BUS_IF) & ~3;
+ if (lp->options & PORT_FD) {
+ val |= 1;
+ if (lp->options == (PORT_FD | PORT_AUI))
+ val |= 2;
+ }
+ outw(val, ioaddr+PCNET32_BUS_IF);
+ }
+
+ /* set/reset GPSI bit in test register */
+ outw (0x007c, ioaddr+PCNET32_ADDR);
+ val = inw(ioaddr+PCNET32_DATA) & ~0x10;
+ if ((lp->options & PORT_PORTSEL) == PORT_GPSI)
+ val |= 0x10;
+ outw(val, ioaddr+PCNET32_DATA);
+
+ lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
lp->init_block.filter[0] = 0x00000000;
lp->init_block.filter[1] = 0x00000000;
if (pcnet32_init_ring(dev))
@@ -535,7 +578,7 @@ pcnet32_init_ring(struct device *dev)
struct pcnet32_private *lp = (struct pcnet32_private *)dev->priv;
int i;
- lp->lock = 0, lp->tx_full = 0;
+ lp->tx_full = 0;
lp->cur_rx = lp->cur_tx = 0;
lp->dirty_rx = lp->dirty_tx = 0;
@@ -633,7 +676,6 @@ pcnet32_start_xmit(struct sk_buff *skb, struct device *dev)
outw(0x0000, ioaddr+PCNET32_ADDR);
printk("%s: pcnet32_start_xmit() called, csr0 %4.4x.\n", dev->name,
inw(ioaddr+PCNET32_DATA));
- outw(0x0000, ioaddr+PCNET32_DATA);
}
/* Block a timer-based transmit from overlapping. This could better be
@@ -643,12 +685,8 @@ pcnet32_start_xmit(struct sk_buff *skb, struct device *dev)
return 1;
}
- if (test_and_set_bit(0, (void*)&lp->lock) != 0) {
- if (pcnet32_debug > 0)
- printk("%s: tx queue lock!.\n", dev->name);
- /* don't clear dev->tbusy flag. */
- return 1;
- }
+ save_flags (flags);
+ cli ();
/* Fill in a Tx ring entry */
@@ -678,15 +716,11 @@ pcnet32_start_xmit(struct sk_buff *skb, struct device *dev)
dev->trans_start = jiffies;
- save_flags(flags);
- cli();
- lp->lock = 0;
if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0)
clear_bit (0, (void *)&dev->tbusy);
else
lp->tx_full = 1;
restore_flags(flags);
-
return 0;
}
@@ -698,6 +732,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
struct pcnet32_private *lp;
unsigned int csr0, ioaddr;
int boguscnt = max_interrupt_work;
+ int must_restart;
if (dev == NULL) {
printk ("pcnet32_interrupt(): irq %d for unknown device.\n", irq);
@@ -716,6 +751,8 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* Acknowledge all of the current interrupt sources ASAP. */
outw(csr0 & ~0x004f, dev->base_addr + PCNET32_DATA);
+ must_restart = 0;
+
if (pcnet32_debug > 5)
printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n",
dev->name, csr0, inw(dev->base_addr + PCNET32_DATA));
@@ -737,7 +774,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (status & 0x4000) {
/* There was an major error, log it. */
- int err_status = le16_to_cpu(lp->tx_ring[entry].misc);
+ int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
lp->stats.tx_errors++;
if (err_status & 0x04000000) lp->stats.tx_aborted_errors++;
if (err_status & 0x08000000) lp->stats.tx_carrier_errors++;
@@ -748,10 +785,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
/* Remove this verbosity later! */
printk("%s: Tx FIFO error! Status %4.4x.\n",
dev->name, csr0);
- /* stop the chip to clear the error condition, then restart */
- outw(0x0000, dev->base_addr + PCNET32_ADDR);
- outw(0x0004, dev->base_addr + PCNET32_DATA);
- pcnet32_restart(dev, 0x0002);
+ must_restart = 1;
}
} else {
if (status & 0x1800)
@@ -805,6 +839,13 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dev->name, csr0);
/* unlike for the lance, there is no restart needed */
}
+
+ if (must_restart) {
+ /* stop the chip to clear the error condition, then restart */
+ outw(0x0000, dev->base_addr + PCNET32_ADDR);
+ outw(0x0004, dev->base_addr + PCNET32_DATA);
+ pcnet32_restart(dev, 0x0002);
+ }
}
/* Clear any other interrupt, and set interrupt enable. */
@@ -1038,9 +1079,9 @@ static void pcnet32_set_multicast_list(struct device *dev)
if (dev->flags&IFF_PROMISC) {
/* Log any net taps. */
printk("%s: Promiscuous mode enabled.\n", dev->name);
- lp->init_block.mode = le16_to_cpu(0x8000);
+ lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PORT_PORTSEL) << 7);
} else {
- lp->init_block.mode = 0x0000;
+ lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
pcnet32_load_multicast (dev);
}
@@ -1052,6 +1093,7 @@ static void pcnet32_set_multicast_list(struct device *dev)
#ifdef MODULE
MODULE_PARM(debug, "i");
+MODULE_PARM(options, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(rx_copybreak, "i");
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 91666827e..c41da1866 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -21,6 +21,10 @@
* - Make sure other end is OK, before sending a packet.
* - Fix immediate timer problem.
*
+ * Al Viro
+ * - Changed {enable,disable}_irq handling to make it work
+ * with new ("stack") semantics.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -120,6 +124,9 @@ static const char *version = "NET3 PLIP version 2.3-parport gniibe@mri.co.jp\n";
#endif
static unsigned int net_debug = NET_DEBUG;
+#define ENABLE(irq) enable_irq(irq)
+#define DISABLE(irq) disable_irq(irq)
+
/* In micro second */
#define PLIP_DELAY_UNIT 1
@@ -333,6 +340,7 @@ static int plip_bh_timeout_error(struct device *dev, struct net_local *nl,
#define OK 0
#define TIMEOUT 1
#define ERROR 2
+#define HS_TIMEOUT 3
typedef int (*plip_func)(struct device *dev, struct net_local *nl,
struct plip_local *snd, struct plip_local *rcv);
@@ -371,13 +379,22 @@ plip_bh_timeout_error(struct device *dev, struct net_local *nl,
int error)
{
unsigned char c0;
+ /*
+ * This is tricky. If we got here from the beginning of send (either
+ * with ERROR or HS_TIMEOUT) we have IRQ enabled. Otherwise it's
+ * already disabled. With the old variant of {enable,disable}_irq()
+ * extra disable_irq() was a no-op. Now it became mortal - it's
+ * unbalanced and thus we'll never re-enable IRQ (until rmmod plip,
+ * that is). So we have to treat HS_TIMEOUT and ERROR from send
+ * in a special way.
+ */
spin_lock_irq(&nl->lock);
if (nl->connection == PLIP_CN_SEND) {
if (error != ERROR) { /* Timeout */
nl->timeout_count++;
- if ((snd->state == PLIP_PK_TRIGGER
+ if ((error == HS_TIMEOUT
&& nl->timeout_count <= 10)
|| nl->timeout_count <= 3) {
spin_unlock_irq(&nl->lock);
@@ -387,7 +404,8 @@ plip_bh_timeout_error(struct device *dev, struct net_local *nl,
c0 = inb(PAR_STATUS(dev));
printk(KERN_WARNING "%s: transmit timeout(%d,%02x)\n",
dev->name, snd->state, c0);
- }
+ } else
+ error = HS_TIMEOUT;
nl->enet_stats.tx_errors++;
nl->enet_stats.tx_aborted_errors++;
} else if (nl->connection == PLIP_CN_RECEIVE) {
@@ -419,8 +437,10 @@ plip_bh_timeout_error(struct device *dev, struct net_local *nl,
snd->skb = NULL;
}
spin_unlock_irq(&nl->lock);
- disable_irq(dev->irq);
- synchronize_irq();
+ if (error == HS_TIMEOUT) {
+ DISABLE(dev->irq);
+ synchronize_irq();
+ }
outb(PAR_INTR_OFF, PAR_CONTROL(dev));
dev->tbusy = 1;
nl->connection = PLIP_CN_ERROR;
@@ -498,7 +518,7 @@ plip_receive_packet(struct device *dev, struct net_local *nl,
switch (rcv->state) {
case PLIP_PK_TRIGGER:
- disable_irq(dev->irq);
+ DISABLE(dev->irq);
/* Don't need to synchronize irq, as we can safely ignore it */
outb(PAR_INTR_OFF, PAR_CONTROL(dev));
dev->interrupt = 0;
@@ -518,7 +538,7 @@ plip_receive_packet(struct device *dev, struct net_local *nl,
nl->connection = PLIP_CN_SEND;
queue_task(&nl->deferred, &tq_timer);
outb(PAR_INTR_ON, PAR_CONTROL(dev));
- enable_irq(dev->irq);
+ ENABLE(dev->irq);
return OK;
}
} else {
@@ -592,13 +612,13 @@ plip_receive_packet(struct device *dev, struct net_local *nl,
queue_task(&nl->immediate, &tq_immediate);
mark_bh(IMMEDIATE_BH);
outb(PAR_INTR_ON, PAR_CONTROL(dev));
- enable_irq(dev->irq);
+ ENABLE(dev->irq);
return OK;
} else {
nl->connection = PLIP_CN_NONE;
spin_unlock_irq(&nl->lock);
outb(PAR_INTR_ON, PAR_CONTROL(dev));
- enable_irq(dev->irq);
+ ENABLE(dev->irq);
return OK;
}
}
@@ -674,7 +694,7 @@ plip_send_packet(struct device *dev, struct net_local *nl,
switch (snd->state) {
case PLIP_PK_TRIGGER:
if ((inb(PAR_STATUS(dev)) & 0xf8) != 0x80)
- return TIMEOUT;
+ return HS_TIMEOUT;
/* Trigger remote rx interrupt. */
outb(0x08, data_addr);
@@ -691,12 +711,16 @@ plip_send_packet(struct device *dev, struct net_local *nl,
c0 = inb(PAR_STATUS(dev));
if (c0 & 0x08) {
spin_unlock_irq(&nl->lock);
- disable_irq(dev->irq);
+ DISABLE(dev->irq);
synchronize_irq();
if (nl->connection == PLIP_CN_RECEIVE) {
/* Interrupted.
We don't need to enable irq,
as it is soon disabled. */
+ /* Yes, we do. New variant of
+ {enable,disable}_irq *counts*
+ them. -- AV */
+ ENABLE(dev->irq);
nl->enet_stats.collisions++;
return OK;
}
@@ -711,7 +735,7 @@ plip_send_packet(struct device *dev, struct net_local *nl,
spin_unlock_irq(&nl->lock);
if (--cx == 0) {
outb(0x00, data_addr);
- return TIMEOUT;
+ return HS_TIMEOUT;
}
}
@@ -760,7 +784,7 @@ plip_send_packet(struct device *dev, struct net_local *nl,
nl->is_deferred = 1;
queue_task(&nl->deferred, &tq_timer);
outb(PAR_INTR_ON, PAR_CONTROL(dev));
- enable_irq(dev->irq);
+ ENABLE(dev->irq);
return OK;
}
return OK;
@@ -800,7 +824,7 @@ plip_error(struct device *dev, struct net_local *nl,
dev->tbusy = 0;
dev->interrupt = 0;
outb(PAR_INTR_ON, PAR_CONTROL(dev));
- enable_irq(dev->irq);
+ ENABLE(dev->irq);
mark_bh(NET_BH);
} else {
nl->is_deferred = 1;
@@ -1000,7 +1024,7 @@ plip_close(struct device *dev)
dev->tbusy = 1;
dev->start = 0;
- disable_irq(dev->irq);
+ DISABLE(dev->irq);
synchronize_irq();
#ifdef NOTDEF
@@ -1203,7 +1227,6 @@ __initfunc(int
plip_init(void))
{
struct parport *pb = parport_enumerate();
- int devices=0;
int i=0;
if (parport[0] == -2)
@@ -1214,7 +1237,7 @@ plip_init(void))
timid = 0;
}
- /* When user feeds parameters, use them */
+ /* If the user feeds parameters, use them */
while (pb) {
if ((parport[0] == -1 && (!timid || !pb->devices)) ||
plip_searchfor(parport, i)) {
@@ -1242,14 +1265,13 @@ plip_init(void))
kfree(dev_plip[i]->name);
kfree(dev_plip[i]);
} else {
- devices++;
+ i++;
}
}
- i++;
pb = pb->next;
}
- if (devices == 0) {
+ if (i == 0) {
printk(KERN_INFO "plip: no devices registered\n");
return -EIO;
}
diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c
index c578ba87d..b2c07b3fa 100644
--- a/drivers/net/ppp.c
+++ b/drivers/net/ppp.c
@@ -4,7 +4,7 @@
* Al Longyear <longyear@netcom.com>
* Extensively rewritten by Paul Mackerras <paulus@cs.anu.edu.au>
*
- * ==FILEVERSION 981004==
+ * ==FILEVERSION 990114==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the number above to the
@@ -1216,6 +1216,7 @@ typedef struct ppp_proto_struct {
} ppp_proto_type;
static int rcv_proto_ip (struct ppp *, struct sk_buff *);
+static int rcv_proto_ipv6 (struct ppp *, struct sk_buff *);
static int rcv_proto_ipx (struct ppp *, struct sk_buff *);
static int rcv_proto_at (struct ppp *, struct sk_buff *);
static int rcv_proto_vjc_comp (struct ppp *, struct sk_buff *);
@@ -1226,6 +1227,7 @@ static int rcv_proto_unknown (struct ppp *, struct sk_buff *);
static
ppp_proto_type proto_list[] = {
{ PPP_IP, rcv_proto_ip },
+ { PPP_IPV6, rcv_proto_ipv6 },
{ PPP_IPX, rcv_proto_ipx },
{ PPP_AT, rcv_proto_at },
{ PPP_VJC_COMP, rcv_proto_vjc_comp },
@@ -2003,6 +2005,19 @@ rcv_proto_ip(struct ppp *ppp, struct sk_buff *skb)
}
/*
+ * Process the receipt of an IPv6 frame
+ */
+static int
+rcv_proto_ipv6(struct ppp *ppp, struct sk_buff *skb)
+{
+ CHECK_PPP(0);
+ if ((ppp2dev(ppp)->flags & IFF_UP) && (skb->len > 0)
+ && ppp->sc_npmode[NP_IPV6] == NPMODE_PASS)
+ return ppp_rcv_rx(ppp, ETH_P_IPV6, skb);
+ return 0;
+}
+
+/*
* Process the receipt of an IPX frame
*/
static int
@@ -2041,7 +2056,7 @@ rcv_proto_vjc_comp(struct ppp *ppp, struct sk_buff *skb)
return 0;
new_count = slhc_uncompress(ppp->slcomp, skb->data + PPP_HDRLEN,
skb->len - PPP_HDRLEN);
- if (new_count < 0) {
+ if (new_count<=0) {
if (ppp->flags & SC_DEBUG)
printk(KERN_NOTICE
"ppp: error in VJ decompression\n");
@@ -2383,6 +2398,10 @@ ppp_dev_xmit(struct sk_buff *skb, struct device *dev)
proto = PPP_IP;
npmode = ppp->sc_npmode[NP_IP];
break;
+ case ETH_P_IPV6:
+ proto = PPP_IPV6;
+ npmode = ppp->sc_npmode[NP_IPV6];
+ break;
case ETH_P_IPX:
proto = PPP_IPX;
npmode = ppp->sc_npmode[NP_IPX];
diff --git a/drivers/net/rcif.h b/drivers/net/rcif.h
new file mode 100644
index 000000000..a41f05aac
--- /dev/null
+++ b/drivers/net/rcif.h
@@ -0,0 +1,299 @@
+/*
+** *************************************************************************
+**
+**
+** R C I F . H
+**
+**
+** RedCreek InterFace include file.
+**
+** ---------------------------------------------------------------------
+** --- Copyright (c) 1998-1999, RedCreek Communications Inc. ---
+** --- All rights reserved. ---
+** ---------------------------------------------------------------------
+**
+** File Description:
+**
+** Header file private ioctl commands.
+**
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+** *************************************************************************
+*/
+
+#ifndef RCIF_H
+#define RCIF_H
+
+/* The following protocol revision # should be incremented every time
+ a new protocol or new structures are used in this file. */
+int USER_PROTOCOL_REV = 2; /* used to track different protocol revisions */
+
+/* define a single TCB & buffer */
+typedef struct /* a single buffer */
+{
+ U32 context; /* context */
+ U32 scount; /* segment count */
+ U32 size; /* segment size */
+ U32 addr; /* segment physical address */
+}
+__attribute__((packed))
+singleB, *psingleB ;
+typedef struct /* a single TCB */
+{
+ /*
+ ** +-----------------------+
+ ** | 1 | one buffer in the TCB
+ ** +-----------------------+
+ ** | <user's Context> | user's buffer reference
+ ** +-----------------------+
+ ** | 1 | one segment buffer
+ ** +-----------------------+ _
+ ** | <buffer size> | size \
+ ** +-----------------------+ \ segment descriptor
+ ** | <physical address> | physical address of buffer /
+ ** +-----------------------+ _/
+ */
+ U32 bcount; /* buffer count */
+ singleB b; /* buffer */
+
+}
+__attribute__((packed))
+singleTCB, *psingleTCB;
+
+/*
+ When adding new entries, please add all 5 related changes, since
+ it helps keep everything consistent:
+ 1) User structure entry
+ 2) User data entry
+ 3) Structure short-cut entry
+ 4) Data short-cut entry
+ 5) Command identifier entry
+
+ For Example ("GETSPEED"):
+ 1) struct RCgetspeed_tag { U32 LinkSpeedCode; } RCgetspeed;
+ 2) struct RCgetspeed_tag *getspeed;
+ 3) #define RCUS_GETSPEED data.RCgetspeed;
+ 4) #define RCUD_GETSPEED _RC_user_data.getspeed
+ 5) #define RCUC_GETSPEED 0x02
+
+ Notes for the "GETSPEED" entry, above:
+ 1) RCgetspeed - RC{name}
+ RCgetspeed_tag - RC{name}_tag
+ LinkSpeedCode - create any structure format desired (not too large,
+ since memory will be unioned with all other entries)
+ 2) RCgetspeed_tag - RC{name}_tag chosen in #1
+ getspeed - arbitrary name (ptr to structure in #1)
+ 3) RCUS_GETSPEED - RCUS_{NAME} ("NAME" & "name" do not have to the same)
+ data.RCgetspeed - data.RC{name} ("RC{name}" from #1)
+ 4) RCUD_GETSPEED - _RC_user_data.getspeed ("getspeed" from #2)
+ 5) RCUC_GETSPEED - unique hex identifier entry.
+*/
+
+typedef struct RC_user_tag RCuser_struct;
+
+/* 1) User structure entry */
+struct RC_user_tag
+{
+ int cmd;
+ union
+ {
+ /* GETINFO structure */
+ struct RCgetinfo_tag {
+ unsigned long int mem_start;
+ unsigned long int mem_end;
+ unsigned long int base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+ } RCgetinfo; /* <---- RCgetinfo */
+
+ /* GETSPEED structure */
+ struct RCgetspeed_tag {
+ U32 LinkSpeedCode;
+ } RCgetspeed; /* <---- RCgetspeed */
+
+ /* SETSPEED structure */
+ struct RCsetspeed_tag {
+ U16 LinkSpeedCode;
+ } RCsetspeed; /* <---- RCsetspeed */
+
+ /* GETPROM structure */
+ struct RCgetprom_tag {
+ U32 PromMode;
+ } RCgetprom; /* <---- RCgetprom */
+
+ /* SETPROM structure */
+ struct RCsetprom_tag {
+ U16 PromMode;
+ } RCsetprom; /* <---- RCsetprom */
+
+ /* GETBROADCAST structure */
+ struct RCgetbroadcast_tag {
+ U32 BroadcastMode;
+ } RCgetbroadcast; /* <---- RCgetbroadcast */
+
+ /* SETBROADCAST structure */
+ struct RCsetbroadcast_tag {
+ U16 BroadcastMode;
+ } RCsetbroadcast; /* <---- RCsetbroadcast */
+
+ /* GETFIRMWAREVER structure */
+ #define FirmStringLen 80
+ struct RCgetfwver_tag {
+ U8 FirmString[FirmStringLen];
+ } RCgetfwver; /* <---- RCgetfwver */
+
+ /* GETIPANDMASK structure */
+ struct RCgetipnmask_tag {
+ U32 IpAddr;
+ U32 NetMask;
+ } RCgetipandmask; /* <---- RCgetipandmask */
+
+ /* SETIPANDMASK structure */
+ struct RCsetipnmask_tag {
+ U32 IpAddr;
+ U32 NetMask;
+ } RCsetipandmask; /* <---- RCsetipandmask */
+
+ /* GETMAC structure */
+ #define MAC_SIZE 10
+ struct RCgetmac_tag {
+ U8 mac[MAC_SIZE];
+ } RCgetmac; /* <---- RCgetmac */
+
+ /* SETMAC structure */
+ struct RCsetmac_tag {
+ U8 mac[MAC_SIZE];
+ } RCsetmac; /* <---- RCsetmac */
+
+ /* GETLINKSTATUS structure */
+ struct RCgetlnkstatus_tag {
+ U32 ReturnStatus;
+ } RCgetlnkstatus; /* <---- RCgetlnkstatus */
+
+ /* GETLINKSTATISTICS structure */
+ struct RCgetlinkstats_tag {
+ RCLINKSTATS StatsReturn;
+ } RCgetlinkstats; /* <---- RCgetlinkstats */
+
+ /* DEFAULT structure (when no command was recognized) */
+ struct RCdefault_tag {
+ int rc;
+ } RCdefault; /* <---- RCdefault */
+
+ } data;
+
+}; /* struct RC_user_tag { ... } */
+
+/* 2) User data entry */
+/* RCUD = RedCreek User Data */
+union RC_user_data_tag { /* structure tags used are taken from RC_user_tag structure above */
+ struct RCgetinfo_tag *getinfo;
+ struct RCgetspeed_tag *getspeed;
+ struct RCgetprom_tag *getprom;
+ struct RCgetbroadcast_tag *getbroadcast;
+ struct RCgetfwver_tag *getfwver;
+ struct RCgetipnmask_tag *getipandmask;
+ struct RCgetmac_tag *getmac;
+ struct RCgetlnkstatus_tag *getlinkstatus;
+ struct RCgetlinkstats_tag *getlinkstatistics;
+ struct RCdefault_tag *rcdefault;
+ struct RCsetspeed_tag *setspeed;
+ struct RCsetprom_tag *setprom;
+ struct RCsetbroadcast_tag *setbroadcast;
+ struct RCsetipnmask_tag *setipandmask;
+ struct RCsetmac_tag *setmac;
+} _RC_user_data; /* declare as a global, so the defines below will work */
+
+/* 3) Structure short-cut entry */
+/* define structure short-cuts */ /* structure names are taken from RC_user_tag structure above */
+#define RCUS_GETINFO data.RCgetinfo;
+#define RCUS_GETSPEED data.RCgetspeed;
+#define RCUS_GETPROM data.RCgetprom;
+#define RCUS_GETBROADCAST data.RCgetbroadcast;
+#define RCUS_GETFWVER data.RCgetfwver;
+#define RCUS_GETIPANDMASK data.RCgetipandmask;
+#define RCUS_GETMAC data.RCgetmac;
+#define RCUS_GETLINKSTATUS data.RCgetlnkstatus;
+#define RCUS_GETLINKSTATISTICS data.RCgetlinkstats;
+#define RCUS_DEFAULT data.RCdefault;
+#define RCUS_SETSPEED data.RCsetspeed;
+#define RCUS_SETPROM data.RCsetprom;
+#define RCUS_SETBROADCAST data.RCsetbroadcast;
+#define RCUS_SETIPANDMASK data.RCsetipandmask;
+#define RCUS_SETMAC data.RCsetmac;
+
+/* 4) Data short-cut entry */
+/* define data short-cuts */ /* pointer names are from RC_user_data_tag union (just below RC_user_tag) */
+#define RCUD_GETINFO _RC_user_data.getinfo
+#define RCUD_GETSPEED _RC_user_data.getspeed
+#define RCUD_GETPROM _RC_user_data.getprom
+#define RCUD_GETBROADCAST _RC_user_data.getbroadcast
+#define RCUD_GETFWVER _RC_user_data.getfwver
+#define RCUD_GETIPANDMASK _RC_user_data.getipandmask
+#define RCUD_GETMAC _RC_user_data.getmac
+#define RCUD_GETLINKSTATUS _RC_user_data.getlinkstatus
+#define RCUD_GETLINKSTATISTICS _RC_user_data.getlinkstatistics
+#define RCUD_DEFAULT _RC_user_data.rcdefault
+#define RCUD_SETSPEED _RC_user_data.setspeed
+#define RCUD_SETPROM _RC_user_data.setprom
+#define RCUD_SETBROADCAST _RC_user_data.setbroadcast
+#define RCUD_SETIPANDMASK _RC_user_data.setipandmask
+#define RCUD_SETMAC _RC_user_data.setmac
+
+/* 5) Command identifier entry */
+/* define command identifiers */
+#define RCUC_GETINFO 0x01
+#define RCUC_GETSPEED 0x02
+#define RCUC_GETFWVER 0x03
+#define RCUC_GETIPANDMASK 0x04
+#define RCUC_GETMAC 0x05
+#define RCUC_GETLINKSTATUS 0x06
+#define RCUC_GETLINKSTATISTICS 0x07
+#define RCUC_GETPROM 0x14
+#define RCUC_GETBROADCAST 0x15
+#define RCUC_DEFAULT 0xff
+#define RCUC_SETSPEED 0x08
+#define RCUC_SETIPANDMASK 0x09
+#define RCUC_SETMAC 0x0a
+#define RCUC_SETPROM 0x16
+#define RCUC_SETBROADCAST 0x17
+
+/* define ioctl commands to use, when talking to RC 45/PCI driver */
+#define RCU_PROTOCOL_REV SIOCDEVPRIVATE
+#define RCU_COMMAND SIOCDEVPRIVATE+1
+
+/*
+ Intended use for the above defines is shown below (GETINFO, as this example):
+
+ RCuser_struct RCuser; // declare RCuser structure
+ struct ifreq ifr; // declare an interface request structure
+
+ RCuser.cmd = RCUC_GETINFO; // set user command to GETINFO
+ ifr->ifr_data = (caddr_t) &RCuser; // set point to user structure
+
+ sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); // get a socket
+ ioctl(sock, RCU_COMMAND, &ifr); // do ioctl on socket
+
+ RCUD_GETINFO = &RCuser.RCUS_GETINFO; // set data pointer for GETINFO
+
+ // print results
+ printf("memory 0x%lx-0x%lx, base address 0x%x, irq 0x%x\n",
+ RCUD_GETINFO->mem_start, RCUD_GETINFO->mem_end,
+ RCUD_GETINFO->base_addr, RCUD_GETINFO->irq);
+*/
+
+#endif /* RCIF_H */
+
diff --git a/drivers/net/rclanmtl.c b/drivers/net/rclanmtl.c
new file mode 100644
index 000000000..971fb49b6
--- /dev/null
+++ b/drivers/net/rclanmtl.c
@@ -0,0 +1,2307 @@
+/*
+** *************************************************************************
+**
+**
+** R C L A N M T L . C $Revision: 5 $
+**
+**
+** RedCreek I2O LAN Message Transport Layer program module.
+**
+** ---------------------------------------------------------------------
+** --- Copyright (c) 1997-1999, RedCreek Communications Inc. ---
+** --- All rights reserved. ---
+** ---------------------------------------------------------------------
+**
+** File Description:
+**
+** Host side I2O (Intelligent I/O) LAN message transport layer.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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.
+** *************************************************************************
+*/
+
+#undef DEBUG
+
+#define RC_LINUX_MODULE
+#include "rclanmtl.h"
+
+#define dprintf kprintf
+
+extern int printk(const char * fmt, ...);
+
+ /* RedCreek LAN device Target ID */
+#define RC_LAN_TARGET_ID 0x10
+ /* RedCreek's OSM default LAN receive Initiator */
+#define DEFAULT_RECV_INIT_CONTEXT 0xA17
+
+
+/*
+** I2O message structures
+*/
+
+#define I2O_TID_SZ 12
+#define I2O_FUNCTION_SZ 8
+
+/* Transaction Reply Lists (TRL) Control Word structure */
+
+#define I2O_TRL_FLAGS_SINGLE_FIXED_LENGTH 0x00
+#define I2O_TRL_FLAGS_SINGLE_VARIABLE_LENGTH 0x40
+#define I2O_TRL_FLAGS_MULTIPLE_FIXED_LENGTH 0x80
+
+/* LAN Class specific functions */
+
+#define I2O_LAN_PACKET_SEND 0x3B
+#define I2O_LAN_SDU_SEND 0x3D
+#define I2O_LAN_RECEIVE_POST 0x3E
+#define I2O_LAN_RESET 0x35
+#define I2O_LAN_SHUTDOWN 0x37
+
+/* Private Class specfic function */
+#define I2O_PRIVATE 0xFF
+
+/* I2O Executive Function Codes. */
+
+#define I2O_EXEC_ADAPTER_ASSIGN 0xB3
+#define I2O_EXEC_ADAPTER_READ 0xB2
+#define I2O_EXEC_ADAPTER_RELEASE 0xB5
+#define I2O_EXEC_BIOS_INFO_SET 0xA5
+#define I2O_EXEC_BOOT_DEVICE_SET 0xA7
+#define I2O_EXEC_CONFIG_VALIDATE 0xBB
+#define I2O_EXEC_CONN_SETUP 0xCA
+#define I2O_EXEC_DEVICE_ASSIGN 0xB7
+#define I2O_EXEC_DEVICE_RELEASE 0xB9
+#define I2O_EXEC_HRT_GET 0xA8
+#define I2O_EXEC_IOP_CLEAR 0xBE
+#define I2O_EXEC_IOP_CONNECT 0xC9
+#define I2O_EXEC_IOP_RESET 0xBD
+#define I2O_EXEC_LCT_NOTIFY 0xA2
+#define I2O_EXEC_OUTBOUND_INIT 0xA1
+#define I2O_EXEC_PATH_ENABLE 0xD3
+#define I2O_EXEC_PATH_QUIESCE 0xC5
+#define I2O_EXEC_PATH_RESET 0xD7
+#define I2O_EXEC_STATIC_MF_CREATE 0xDD
+#define I2O_EXEC_STATIC_MF_RELEASE 0xDF
+#define I2O_EXEC_STATUS_GET 0xA0
+#define I2O_EXEC_SW_DOWNLOAD 0xA9
+#define I2O_EXEC_SW_UPLOAD 0xAB
+#define I2O_EXEC_SW_REMOVE 0xAD
+#define I2O_EXEC_SYS_ENABLE 0xD1
+#define I2O_EXEC_SYS_MODIFY 0xC1
+#define I2O_EXEC_SYS_QUIESCE 0xC3
+#define I2O_EXEC_SYS_TAB_SET 0xA3
+
+
+ /* Init Outbound Q status */
+#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01
+#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02
+#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03
+#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04
+
+
+#define I2O_UTIL_NOP 0x00
+
+
+/* I2O Get Status State values */
+
+#define I2O_IOP_STATE_INITIALIZING 0x01
+#define I2O_IOP_STATE_RESET 0x02
+#define I2O_IOP_STATE_HOLD 0x04
+#define I2O_IOP_STATE_READY 0x05
+#define I2O_IOP_STATE_OPERATIONAL 0x08
+#define I2O_IOP_STATE_FAILED 0x10
+#define I2O_IOP_STATE_FAULTED 0x11
+
+
+/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */
+
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
+#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
+#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
+#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
+#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x07
+#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x08
+#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x09
+#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A
+#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
+
+
+/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/
+
+#define I2O_DETAIL_STATUS_SUCCESS 0x0000
+#define I2O_DETAIL_STATUS_BAD_KEY 0x0001
+#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0002
+#define I2O_DETAIL_STATUS_DEVICE_BUSY 0x0003
+#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x0004
+#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x0005
+#define I2O_DETAIL_STATUS_DEVICE_RESET 0x0006
+#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x0007
+#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0008
+#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0009
+#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000A
+#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000B
+#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x000C
+#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x000D
+#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x000E
+#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x000F
+#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0010
+#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0011
+#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0012
+#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0013
+#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0014
+#define I2O_DETAIL_STATUS_TCL_ERROR 0x0015
+#define I2O_DETAIL_STATUS_TIMEOUT 0x0016
+#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0017
+#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0018
+#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x0019
+#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A
+
+ /* I2O msg header defines for VersionOffset */
+#define I2OMSGVER_1_5 0x0001
+#define SGL_OFFSET_0 I2OMSGVER_1_5
+#define SGL_OFFSET_4 (0x0040 | I2OMSGVER_1_5)
+#define TRL_OFFSET_5 (0x0050 | I2OMSGVER_1_5)
+#define TRL_OFFSET_6 (0x0060 | I2OMSGVER_1_5)
+
+ /* I2O msg header defines for MsgFlags */
+#define MSG_STATIC 0x0100
+#define MSG_64BIT_CNTXT 0x0200
+#define MSG_MULTI_TRANS 0x1000
+#define MSG_FAIL 0x2000
+#define MSG_LAST 0x4000
+#define MSG_REPLY 0x8000
+
+ /* normal LAN request message MsgFlags and VersionOffset (0x1041) */
+#define LAN_MSG_REQST (MSG_MULTI_TRANS | SGL_OFFSET_4)
+
+ /* minimum size msg */
+#define THREE_WORD_MSG_SIZE 0x00030000
+#define FOUR_WORD_MSG_SIZE 0x00040000
+#define FIVE_WORD_MSG_SIZE 0x00050000
+#define SIX_WORD_MSG_SIZE 0x00060000
+#define SEVEN_WORD_MSG_SIZE 0x00070000
+#define EIGHT_WORD_MSG_SIZE 0x00080000
+#define NINE_WORD_MSG_SIZE 0x00090000
+
+/* Special TID Assignments */
+
+#define I2O_IOP_TID 0
+#define I2O_HOST_TID 1
+
+ /* RedCreek I2O private message codes */
+#define RC_PRIVATE_GET_MAC_ADDR 0x0001/**/ /* OBSOLETE */
+#define RC_PRIVATE_SET_MAC_ADDR 0x0002
+#define RC_PRIVATE_GET_NIC_STATS 0x0003
+#define RC_PRIVATE_GET_LINK_STATUS 0x0004
+#define RC_PRIVATE_SET_LINK_SPEED 0x0005
+#define RC_PRIVATE_SET_IP_AND_MASK 0x0006
+/* #define RC_PRIVATE_GET_IP_AND_MASK 0x0007 */ /* OBSOLETE */
+#define RC_PRIVATE_GET_LINK_SPEED 0x0008
+#define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
+/* #define RC_PRIVATE_GET_MAC_ADDR 0x000A *//**/
+#define RC_PRIVATE_GET_IP_AND_MASK 0x000B /**/
+#define RC_PRIVATE_DEBUG_MSG 0x000C
+#define RC_PRIVATE_REPORT_DRIVER_CAPABILITY 0x000D
+#define RC_PRIVATE_SET_PROMISCUOUS_MODE 0x000e
+#define RC_PRIVATE_GET_PROMISCUOUS_MODE 0x000f
+#define RC_PRIVATE_SET_BROADCAST_MODE 0x0010
+#define RC_PRIVATE_GET_BROADCAST_MODE 0x0011
+
+#define RC_PRIVATE_REBOOT 0x00FF
+
+
+/* I2O message header */
+typedef struct _I2O_MESSAGE_FRAME
+{
+ U8 VersionOffset;
+ U8 MsgFlags;
+ U16 MessageSize;
+ BF TargetAddress:I2O_TID_SZ;
+ BF InitiatorAddress:I2O_TID_SZ;
+ BF Function:I2O_FUNCTION_SZ;
+ U32 InitiatorContext;
+ /* SGL[] */
+}
+I2O_MESSAGE_FRAME, *PI2O_MESSAGE_FRAME;
+
+
+ /* assumed a 16K minus 256 byte space for outbound queue message frames */
+#define MSG_FRAME_SIZE 512
+#define NMBR_MSG_FRAMES 30
+
+/*
+** Message Unit CSR definitions for RedCreek PCI45 board
+*/
+typedef struct tag_rcatu
+{
+ volatile unsigned long APICRegSel; /* APIC Register Select */
+ volatile unsigned long reserved0;
+ volatile unsigned long APICWinReg; /* APIC Window Register */
+ volatile unsigned long reserved1;
+ volatile unsigned long InMsgReg0; /* inbound message register 0 */
+ volatile unsigned long InMsgReg1; /* inbound message register 1 */
+ volatile unsigned long OutMsgReg0; /* outbound message register 0 */
+ volatile unsigned long OutMsgReg1; /* outbound message register 1 */
+ volatile unsigned long InDoorReg; /* inbound doorbell register */
+ volatile unsigned long InIntStat; /* inbound interrupt status register */
+ volatile unsigned long InIntMask; /* inbound interrupt mask register */
+ volatile unsigned long OutDoorReg; /* outbound doorbell register */
+ volatile unsigned long OutIntStat; /* outbound interrupt status register */
+ volatile unsigned long OutIntMask; /* outbound interrupt mask register */
+ volatile unsigned long reserved2;
+ volatile unsigned long reserved3;
+ volatile unsigned long InQueue; /* inbound queue port */
+ volatile unsigned long OutQueue; /* outbound queue port */
+ volatile unsigned long reserved4;
+ volatile unsigned long reserver5;
+ /* RedCreek extension */
+ volatile unsigned long EtherMacLow;
+ volatile unsigned long EtherMacHi;
+ volatile unsigned long IPaddr;
+ volatile unsigned long IPmask;
+}
+ATU, *PATU;
+
+ /*
+ ** typedef PAB
+ **
+ ** PCI Adapter Block - holds instance specific information and is located
+ ** in a reserved space at the start of the message buffer allocated by user.
+ */
+typedef struct
+{
+ PATU p_atu; /* ptr to ATU register block */
+ PU8 pPci45LinBaseAddr;
+ PU8 pLinOutMsgBlock;
+ U32 outMsgBlockPhyAddr;
+ PFNTXCALLBACK pTransCallbackFunc;
+ PFNRXCALLBACK pRecvCallbackFunc;
+ PFNCALLBACK pRebootCallbackFunc;
+ PFNCALLBACK pCallbackFunc;
+ U16 IOPState;
+ U16 InboundMFrameSize;
+}
+PAB, *PPAB;
+
+ /*
+ ** in reserved space right after PAB in host memory is area for returning
+ ** values from card
+ */
+
+ /*
+ ** Array of pointers to PCI Adapter Blocks.
+ ** Indexed by a zero based (0-31) interface number.
+ */
+#define MAX_ADAPTERS 32
+static PPAB PCIAdapterBlock[MAX_ADAPTERS] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+/*
+** typedef NICSTAT
+**
+** Data structure for NIC statistics retruned from PCI card. Data copied from
+** here to user allocated RCLINKSTATS (see rclanmtl.h) structure.
+*/
+typedef struct tag_NicStat
+{
+ unsigned long TX_good;
+ unsigned long TX_maxcol;
+ unsigned long TX_latecol;
+ unsigned long TX_urun;
+ unsigned long TX_crs; /* lost carrier sense */
+ unsigned long TX_def; /* transmit deferred */
+ unsigned long TX_singlecol; /* single collisions */
+ unsigned long TX_multcol;
+ unsigned long TX_totcol;
+ unsigned long Rcv_good;
+ unsigned long Rcv_CRCerr;
+ unsigned long Rcv_alignerr;
+ unsigned long Rcv_reserr; /* rnr'd pkts */
+ unsigned long Rcv_orun;
+ unsigned long Rcv_cdt;
+ unsigned long Rcv_runt;
+ unsigned long dump_status; /* last field directly from the chip */
+}
+NICSTAT, *P_NICSTAT;
+
+
+#define DUMP_DONE 0x0000A005 /* completed statistical dump */
+#define DUMP_CLEAR 0x0000A007 /* completed stat dump and clear counters */
+
+
+static volatile int msgFlag;
+
+
+/* local function prototypes */
+static void ProcessOutboundI2OMsg(PPAB pPab, U32 phyMsgAddr);
+static int FillI2OMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock);
+static int GetI2OStatus(PPAB pPab);
+static int SendI2OOutboundQInitMsg(PPAB pPab);
+static int SendEnableSysMsg(PPAB pPab);
+
+
+/* 1st 100h bytes of message block is reserved for messenger instance */
+#define ADAPTER_BLOCK_RESERVED_SPACE 0x100
+
+/*
+** =========================================================================
+** RCInitI2OMsgLayer()
+**
+** Initialize the RedCreek I2O Module and adapter.
+**
+** Inputs: AdapterID - interface number from 0 to 15
+** pciBaseAddr - virual base address of PCI (set by BIOS)
+** p_msgbuf - virual address to private message block (min. 16K)
+** p_phymsgbuf - physical address of private message block
+** TransmitCallbackFunction - address of transmit callback function
+** ReceiveCallbackFunction - address of receive callback function
+**
+** private message block is allocated by user. It must be in locked pages.
+** p_msgbuf and p_phymsgbuf point to the same location. Must be contigous
+** memory block of a minimum of 16K byte and long word aligned.
+** =========================================================================
+*/
+RC_RETURN
+RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr,
+ PU8 p_msgbuf, PU8 p_phymsgbuf,
+ PFNTXCALLBACK TransmitCallbackFunction,
+ PFNRXCALLBACK ReceiveCallbackFunction,
+ PFNCALLBACK RebootCallbackFunction)
+{
+ int result;
+ PPAB pPab;
+
+#ifdef DEBUG
+ kprintf("InitI2O: Adapter:0x%04.4ux ATU:0x%08.8ulx msgbuf:0x%08.8ulx phymsgbuf:0x%08.8ulx\n"
+ "TransmitCallbackFunction:0x%08.8ulx ReceiveCallbackFunction:0x%08.8ulx\n",
+ AdapterID, pciBaseAddr, p_msgbuf, p_phymsgbuf, TransmitCallbackFunction, ReceiveCallbackFunction);
+#endif /* DEBUG */
+
+
+ /* Check if this interface already initialized - if so, shut it down */
+ if (PCIAdapterBlock[AdapterID] != NULL)
+ {
+ printk("PCIAdapterBlock[%d]!=NULL\n", AdapterID);
+// RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+ PCIAdapterBlock[AdapterID] = NULL;
+ }
+
+ /*
+ ** store adapter instance values in adapter block.
+ ** Adapter block is at beginning of message buffer
+ */
+ pPab = (PPAB)p_msgbuf;
+
+ pPab->p_atu = (PATU)pciBaseAddr;
+ pPab->pPci45LinBaseAddr = (PU8)pciBaseAddr;
+
+ /* Set outbound message frame addr - skip over Adapter Block */
+ pPab->outMsgBlockPhyAddr = (U32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+ pPab->pLinOutMsgBlock = (PU8)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+
+ /* store callback function addresses */
+ pPab->pTransCallbackFunc = TransmitCallbackFunction;
+ pPab->pRecvCallbackFunc = ReceiveCallbackFunction;
+ pPab->pRebootCallbackFunc = RebootCallbackFunction;
+ pPab->pCallbackFunc = (PFNCALLBACK)NULL;
+
+ /*
+ ** Initialize I2O IOP
+ */
+ result = GetI2OStatus(pPab);
+
+ if (result != RC_RTN_NO_ERROR)
+ return result;
+
+ if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL)
+ {
+ printk("pPab->IOPState == op: resetting adapter\n");
+ RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+ }
+
+ result = SendI2OOutboundQInitMsg(pPab);
+
+ if (result != RC_RTN_NO_ERROR)
+ return result;
+
+ result = SendEnableSysMsg(pPab);
+
+ if (result != RC_RTN_NO_ERROR)
+ return result;
+
+ PCIAdapterBlock[AdapterID] = pPab;
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time
+** but can be disabled and re-enabled through these two function calls.
+** Packets will still be put into any posted received buffers and packets will
+** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts
+** will prevent hardware interrupt to host even though the outbound I2O msg
+** queue is not emtpy.
+** =========================================================================
+*/
+#define i960_OUT_POST_Q_INT_BIT 0x0008 /* bit set masks interrupts */
+
+RC_RETURN RCDisableI2OInterrupts(U16 AdapterID)
+{
+ PPAB pPab;
+
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT;
+
+ return RC_RTN_NO_ERROR;
+}
+
+RC_RETURN RCEnableI2OInterrupts(U16 AdapterID)
+{
+ PPAB pPab;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT;
+
+ return RC_RTN_NO_ERROR;
+
+}
+
+
+/*
+** =========================================================================
+** RCI2OSendPacket()
+** =========================================================================
+*/
+RC_RETURN
+RCI2OSendPacket(U16 AdapterID, U32 InitiatorContext, PRCTCB pTransCtrlBlock)
+{
+ U32 msgOffset;
+ PU32 pMsg;
+ int size;
+ PPAB pPab;
+
+#ifdef DEBUG
+ kprintf("RCI2OSendPacket()...\n");
+#endif /* DEBUG */
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ /* get Inbound free Q entry - reading from In Q gets free Q entry */
+ /* offset to Msg Frame in PCI msg block */
+
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("RCI2OSendPacket(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
+
+ if (size == -1) /* error processing TCB - send NOP msg */
+ {
+#ifdef DEBUG
+ kprintf("RCI2OSendPacket(): Error Rrocess TCB!\n");
+#endif /* DEBUG */
+ pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ return RC_RTN_TCB_ERROR;
+ }
+ else /* send over msg header */
+ {
+ pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
+ pMsg[1] = I2O_LAN_PACKET_SEND << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = InitiatorContext;
+ pMsg[3] = 0; /* batch reply */
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+ return RC_RTN_NO_ERROR;
+ }
+}
+
+
+/*
+** =========================================================================
+** RCI2OPostRecvBuffer()
+**
+** inputs: pBufrCntrlBlock - pointer to buffer control block
+**
+** returns TRUE if successful in sending message, else FALSE.
+** =========================================================================
+*/
+RC_RETURN
+RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransCtrlBlock)
+{
+ U32 msgOffset;
+ PU32 pMsg;
+ int size;
+ PPAB pPab;
+
+#ifdef DEBUG
+ kprintf("RCPostRecvBuffers()...\n");
+#endif /* DEBUG */
+
+ /* search for DeviceHandle */
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+
+ /* get Inbound free Q entry - reading from In Q gets free Q entry */
+ /* offset to Msg Frame in PCI msg block */
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("RCPostRecvBuffers(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+
+ }
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ size = FillI2OMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
+
+ if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */
+ {
+#ifdef DEBUG
+ kprintf("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
+#endif /* DEBUG */
+ pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ /* post to Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+ return RC_RTN_TCB_ERROR;
+ }
+ else /* send over size msg header */
+ {
+ pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
+ pMsg[1] = I2O_LAN_RECEIVE_POST << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */
+ /* post to Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+ return RC_RTN_NO_ERROR;
+ }
+}
+
+
+/*
+** =========================================================================
+** RCProcI2OMsgQ()
+**
+** Process I2O outbound message queue until empty.
+** =========================================================================
+*/
+void
+RCProcI2OMsgQ(U16 AdapterID)
+{
+ U32 phyAddrMsg;
+ PU8 p8Msg;
+ PU32 p32;
+ U16 count;
+ PPAB pPab;
+ unsigned char debug_msg[20];
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return;
+
+ phyAddrMsg = pPab->p_atu->OutQueue;
+
+ while (phyAddrMsg != 0xFFFFFFFF)
+ {
+ p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+ p32 = (PU32)p8Msg;
+
+ //printk(" msg: 0x%x 0x%x \n", p8Msg[7], p32[5]);
+
+ /*
+ ** Send Packet Reply Msg
+ */
+ if (I2O_LAN_PACKET_SEND == p8Msg[7]) /* function code byte */
+ {
+ count = *(PU16)(p8Msg+2);
+ count -= p8Msg[0] >> 4;
+ /* status, count, context[], adapter */
+ (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, AdapterID);
+ }
+ /*
+ ** Receive Packet Reply Msg */
+ else if (I2O_LAN_RECEIVE_POST == p8Msg[7])
+ {
+#ifdef DEBUG
+ kprintf("I2O_RECV_REPLY pPab:0x%08.8ulx p8Msg:0x%08.8ulx p32:0x%08.8ulx\n", pPab, p8Msg, p32);
+ kprintf("msg: 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+ p32[0], p32[1], p32[2], p32[3]);
+ kprintf(" 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+ p32[4], p32[5], p32[6], p32[7]);
+ kprintf(" 0x%08.8ulx:0X%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+ p32[8], p32[9], p32[10], p32[11]);
+#endif
+ /* status, count, buckets remaining, packetParmBlock, adapter */
+ (*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, AdapterID);
+
+
+ }
+ else if (I2O_LAN_RESET == p8Msg[7] || I2O_LAN_SHUTDOWN == p8Msg[7])
+ {
+ if (pPab->pCallbackFunc)
+ {
+ (*pPab->pCallbackFunc)(p8Msg[19],0,0,AdapterID);
+ }
+ else
+ {
+ pPab->pCallbackFunc = (PFNCALLBACK) 1;
+ }
+ //PCIAdapterBlock[AdapterID] = 0;
+ }
+ else if (I2O_PRIVATE == p8Msg[7])
+ {
+ //printk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
+ switch (p32[5])
+ {
+ case RC_PRIVATE_DEBUG_MSG:
+ msgFlag = 1;
+ /*printk("Received I2O_PRIVATE msg\n");*/
+ debug_msg[15] = (p32[6]&0xff000000) >> 24;
+ debug_msg[14] = (p32[6]&0x00ff0000) >> 16;
+ debug_msg[13] = (p32[6]&0x0000ff00) >> 8;
+ debug_msg[12] = (p32[6]&0x000000ff);
+
+ debug_msg[11] = (p32[7]&0xff000000) >> 24;
+ debug_msg[10] = (p32[7]&0x00ff0000) >> 16;
+ debug_msg[ 9] = (p32[7]&0x0000ff00) >> 8;
+ debug_msg[ 8] = (p32[7]&0x000000ff);
+
+ debug_msg[ 7] = (p32[8]&0xff000000) >> 24;
+ debug_msg[ 6] = (p32[8]&0x00ff0000) >> 16;
+ debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8;
+ debug_msg[ 4] = (p32[8]&0x000000ff);
+
+ debug_msg[ 3] = (p32[9]&0xff000000) >> 24;
+ debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16;
+ debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8;
+ debug_msg[ 0] = (p32[9]&0x000000ff);
+
+ debug_msg[16] = '\0';
+ printk (debug_msg);
+ break;
+ case RC_PRIVATE_REBOOT:
+ printk("Adapter reboot initiated...\n");
+ if (pPab->pRebootCallbackFunc)
+ {
+ (*pPab->pRebootCallbackFunc)(0,0,0,AdapterID);
+ }
+ break;
+ default:
+ printk("Unknown private I2O msg received: 0x%x\n",
+ p32[5]);
+ break;
+ }
+ }
+
+ /*
+ ** Process other Msg's
+ */
+ else
+ {
+ ProcessOutboundI2OMsg(pPab, phyAddrMsg);
+ }
+
+ /* return MFA to outbound free Q*/
+ pPab->p_atu->OutQueue = phyAddrMsg;
+
+ /* any more msgs? */
+ phyAddrMsg = pPab->p_atu->OutQueue;
+ }
+}
+
+
+/*
+** =========================================================================
+** Returns LAN interface statistical counters to space provided by caller at
+** StatsReturnAddr. Returns 0 if success, else RC_RETURN code.
+** This function will call the WaitCallback function provided by
+** user while waiting for card to respond.
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkStatistics(U16 AdapterID,
+ P_RCLINKSTATS StatsReturnAddr,
+ PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset;
+ volatile U32 timeout;
+ volatile PU32 pMsg;
+ volatile PU32 p32, pReturnAddr;
+ P_NICSTAT pStats;
+ int i;
+ PPAB pPab;
+
+/*kprintf("Get82558Stats() StatsReturnAddr:0x%08.8ulx\n", StatsReturnAddr);*/
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("Get8255XStats(): Inbound Free Q empty!\n");
+#endif
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+/*dprintf("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintf("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = 0x112; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+
+ pStats = (P_NICSTAT)p32;
+ pStats->dump_status = 0xFFFFFFFF;
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+ timeout = 100000;
+ while (1)
+ {
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++)
+ ;
+
+ if (pStats->dump_status != 0xFFFFFFFF)
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("RCGet82558Stats() Timeout waiting for NIC statistics\n");
+#endif
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+
+ pReturnAddr = (PU32)StatsReturnAddr;
+
+ /* copy Nic stats to user's structure */
+ for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++)
+ pReturnAddr[i] = p32[i];
+
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** Get82558LinkStatus()
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkStatus(U16 AdapterID, PU32 ReturnAddr, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset;
+ volatile U32 timeout;
+ volatile PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+/*kprintf("Get82558LinkStatus() ReturnPhysAddr:0x%08.8ulx\n", ReturnAddr);*/
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ dprintf("Get82558LinkStatus(): Inbound Free Q empty!\n");
+#endif
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+/*dprintf("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintf("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = 0x112; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ *p32 = 0xFFFFFFFF;
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+ timeout = 100000;
+ while (1)
+ {
+ U32 i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++)
+ ;
+
+ if (*p32 != 0xFFFFFFFF)
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout waiting for link status\n");
+#endif
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+
+ *ReturnAddr = *p32; /* 1 = up 0 = down */
+
+ return RC_RTN_NO_ERROR;
+
+}
+
+/*
+** =========================================================================
+** RCGetMAC()
+**
+** get the MAC address the adapter is listening for in non-promiscous mode.
+** MAC address is in media format.
+** =========================================================================
+*/
+RC_RETURN
+RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback)
+{
+ unsigned i, timeout;
+ U32 off;
+ PU32 p;
+ U32 temp[2];
+ PPAB pPab;
+ PATU p_atu;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ p_atu = pPab->p_atu;
+
+ p_atu->EtherMacLow = 0; /* first zero return data */
+ p_atu->EtherMacHi = 0;
+
+ off = p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ p = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+#ifdef RCDEBUG
+ printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
+ (uint)p_atu, (uint)off, (uint)p);
+#endif /* RCDEBUG */
+ /* setup private message */
+ p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ p[2] = 0; /* initiator context */
+ p[3] = 0x218; /* transaction context */
+ p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR;
+
+
+ p_atu->InQueue = off; /* send it to the I2O device */
+#ifdef RCDEBUG
+ printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n",
+ (uint)p_atu, (uint)off, (uint)p);
+#endif /* RCDEBUG */
+
+ /* wait for the rcpci45 board to update the info */
+ timeout = 1000000;
+ while (0 == p_atu->EtherMacLow)
+ {
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++)
+ ;
+
+ if (!timeout--)
+ {
+ printk("rc_getmac: Timeout\n");
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+
+ /* read the mac address */
+ temp[0] = p_atu->EtherMacLow;
+ temp[1] = p_atu->EtherMacHi;
+ memcpy((char *)mac, (char *)temp, 6);
+
+
+#ifdef RCDEBUG
+// printk("rc_getmac: 0x%X\n", ptr);
+#endif /* RCDEBUG */
+
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** RCSetMAC()
+**
+** set MAC address the adapter is listening for in non-promiscous mode.
+** MAC address is in media format.
+** =========================================================================
+*/
+RC_RETURN
+RCSetMAC(U16 AdapterID, PU8 mac)
+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR;
+ pMsg[5] = *(unsigned *)mac; /* first four bytes */
+ pMsg[6] = *(unsigned *)(mac + 4); /* last two bytes */
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ return RC_RTN_NO_ERROR ;
+}
+
+
+/*
+** =========================================================================
+** RCSetLinkSpeed()
+**
+** set ethernet link speed.
+** input: speedControl - determines action to take as follows
+** 0 = reset and auto-negotiate (NWay)
+** 1 = Full Duplex 100BaseT
+** 2 = Half duplex 100BaseT
+** 3 = Full Duplex 10BaseT
+** 4 = Half duplex 10BaseT
+** all other values are ignore (do nothing)
+** =========================================================================
+*/
+RC_RETURN
+RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode)
+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED;
+ pMsg[5] = LinkSpeedCode; /* link speed code */
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================
+** RCSetPromiscuousMode()
+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/
+RC_RETURN
+RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_PROMISCUOUS_MODE;
+ pMsg[5] = Mode; /* promiscuous mode setting */
+
+ pPab->p_atu->InQueue = off; /* send it to the device */
+
+ return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================
+** RCGetPromiscuousMode()
+**
+** get promiscuous mode setting
+**
+** Possible return values placed in pMode:
+** 0 = promisuous mode not set
+** 1 = promisuous mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for promiscuous mode from adapter\n");
+ kprintf("0x%08.8ulx\n", p32[0]);
+ return RC_RTN_NO_LINK_SPEED;
+ }
+ }
+
+ /* get mode */
+ *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+
+ return RC_RTN_NO_ERROR;
+}
+/*
+** =========================================================================
+** RCSetBroadcastMode()
+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/
+RC_RETURN
+RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_BROADCAST_MODE;
+ pMsg[5] = Mode; /* promiscuous mode setting */
+
+ pPab->p_atu->InQueue = off; /* send it to the device */
+
+ return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================
+** RCGetBroadcastMode()
+**
+** get promiscuous mode setting
+**
+** Possible return values placed in pMode:
+** 0 = promisuous mode not set
+** 1 = promisuous mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for promiscuous mode from adapter\n");
+ kprintf("0x%08.8ulx\n", p32[0]);
+ return RC_RTN_NO_LINK_SPEED;
+ }
+ }
+
+ /* get mode */
+ *pMode = (U8)((volatile PU8)p32)[0] & 0x0f;
+
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCGetLinkSpeed()
+**
+** get ethernet link speed.
+**
+** 0 = Unknown
+** 1 = Full Duplex 100BaseT
+** 2 = Half duplex 100BaseT
+** 3 = Full Duplex 10BaseT
+** 4 = Half duplex 10BaseT
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ U8 IOPLinkSpeed;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for link speed from IOP\n");
+ kprintf("0x%08.8ulx\n", p32[0]);
+ return RC_RTN_NO_LINK_SPEED;
+ }
+ }
+
+ /* get Link speed */
+ IOPLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f;
+
+ *pLinkSpeedCode= IOPLinkSpeed;
+
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCReportDriverCapability(U16 AdapterID, U32 capability)
+**
+** Currently defined bits:
+** WARM_REBOOT_CAPABLE 0x01
+**
+** =========================================================================
+*/
+RC_RETURN
+RCReportDriverCapability(U16 AdapterID, U32 capability)
+{
+ U32 off;
+ PU32 pMsg;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY;
+ pMsg[5] = capability;
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ return RC_RTN_NO_ERROR ;
+}
+
+/*
+** =========================================================================
+** RCGetFirmwareVer()
+**
+** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+ PPAB pPab;
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ kprintf("RCGetFirmwareVer(): Inbound Free Q empty!\n");
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ /* virtual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0xff;
+
+ /* setup private message */
+ pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
+ /* phys address to return status - area right after PAB */
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] != 0xff)
+ break;
+
+ if (!timeout--)
+ {
+ kprintf("Timeout waiting for link speed from IOP\n");
+ return RC_RTN_NO_FIRM_VER;
+ }
+ }
+
+ strcpy(pFirmString, (PU8)p32);
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCResetLANCard()
+**
+** ResourceFlags indicates whether to return buffer resource explicitly
+** to host or keep and reuse.
+** CallbackFunction (if not NULL) is the function to be called when
+** reset is complete.
+** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
+** reset is done (if not NULL).
+**
+** =========================================================================
+*/
+RC_RETURN
+RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+ unsigned long off;
+ unsigned long *pMsg;
+ PPAB pPab;
+ int i;
+ long timeout = 0;
+
+
+ pPab =PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pPab->pCallbackFunc = CallbackFunction;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup message */
+ pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_LAN_RESET << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = ResourceFlags << 16; /* resource flags */
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ if (CallbackFunction == (PFNCALLBACK)NULL)
+ {
+ /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
+ or until timer goes off */
+ while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
+ {
+ RCProcI2OMsgQ(AdapterID);
+ for (i = 0; i < 100000; i++) /* please don't hog the bus!!! */
+ ;
+ timeout++;
+ if (timeout > 10000)
+ {
+ break;
+ }
+ }
+ if (ReturnAddr != (PU32)NULL)
+ *ReturnAddr = (U32)pPab->pCallbackFunc;
+ }
+
+ return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================
+** RCResetIOP()
+**
+** Send StatusGet Msg, wait for results return directly to buffer.
+**
+** =========================================================================
+*/
+RC_RETURN
+RCResetIOP(U16 AdapterID)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ PPAB pPab;
+ volatile PU32 p32;
+
+ pPab = PCIAdapterBlock[AdapterID];
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virtual address of msg - virtual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_EXEC_IOP_RESET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = 0; /* universal context */
+ pMsg[3] = 0; /* universal context */
+ pMsg[4] = 0; /* universal context */
+ pMsg[5] = 0; /* universal context */
+ /* phys address to return status - area right after PAB */
+ pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+ pMsg[7] = 0;
+ pMsg[8] = 1; /* return 1 byte */
+
+ /* virual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0;
+ p32[1] = 0;
+
+ /* post to Inbound Post Q */
+
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] || p32[1])
+ break;
+
+ if (!timeout--)
+ {
+ printk("RCResetIOP timeout\n");
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCShutdownLANCard()
+**
+** ResourceFlags indicates whether to return buffer resource explicitly
+** to host or keep and reuse.
+** CallbackFunction (if not NULL) is the function to be called when
+** shutdown is complete.
+** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
+** shutdown is done (if not NULL).
+**
+** =========================================================================
+*/
+RC_RETURN
+RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+ volatile PU32 pMsg;
+ U32 off;
+ PPAB pPab;
+ int i;
+ long timeout = 0;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pPab->pCallbackFunc = CallbackFunction;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup message */
+ pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_LAN_SHUTDOWN << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = ResourceFlags << 16; /* resource flags */
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+
+ if (CallbackFunction == (PFNCALLBACK)NULL)
+ {
+ /* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
+ or until timer goes off */
+ while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
+ {
+ RCProcI2OMsgQ(AdapterID);
+ for (i = 0; i < 100000; i++) /* please don't hog the bus!!! */
+ ;
+ timeout++;
+ if (timeout > 10000)
+ {
+ printk("RCShutdownLANCard(): timeout\n");
+ break;
+ }
+ }
+ if (ReturnAddr != (PU32)NULL)
+ *ReturnAddr = (U32)pPab->pCallbackFunc;
+ }
+ return RC_RTN_NO_ERROR ;
+}
+
+
+/*
+** =========================================================================
+** RCSetRavlinIPandMask()
+**
+** Set the Ravlin 45/PCI cards IP address and network mask.
+**
+** IP address and mask must be in network byte order.
+** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+** 0x04030201 and 0x00FFFFFF on a little endian machine.
+**
+** =========================================================================
+*/
+RC_RETURN
+RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask)
+{
+ volatile PU32 pMsg;
+ U32 off;
+ PPAB pPab;
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ off = pPab->p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+ /* setup private message */
+ pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x219; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK;
+ pMsg[5] = ipAddr;
+ pMsg[6] = netMask;
+
+
+ pPab->p_atu->InQueue = off; /* send it to the I2O device */
+ return RC_RTN_NO_ERROR ;
+
+}
+
+/*
+** =========================================================================
+** RCGetRavlinIPandMask()
+**
+** get the IP address and MASK from the card
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask,
+ PFNWAITCALLBACK WaitCallback)
+{
+ unsigned i, timeout;
+ U32 off;
+ PU32 pMsg, p32;
+ PPAB pPab;
+ PATU p_atu;
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
+#endif /* DEBUG */
+
+ pPab = PCIAdapterBlock[AdapterID];
+
+ if (pPab == NULL)
+ return RC_RTN_ADPTR_NOT_REGISTERED;
+
+ p_atu = pPab->p_atu;
+ off = p_atu->InQueue; /* get addresss of message */
+
+ if (0xFFFFFFFF == off)
+ return RC_RTN_FREE_Q_EMPTY;
+
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ *p32 = 0xFFFFFFFF;
+
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
+#endif /* DEBUG */
+ /* setup private message */
+ pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
+ pMsg[2] = 0; /* initiator context */
+ pMsg[3] = 0x218; /* transaction context */
+ pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
+ pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ p_atu->InQueue = off; /* send it to the I2O device */
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
+#endif /* DEBUG */
+
+ /* wait for the rcpci45 board to update the info */
+ timeout = 100000;
+ while (0xffffffff == *p32)
+ {
+ if (WaitCallback)
+ (*WaitCallback)();
+
+ for (i = 0; i < 1000; i++)
+ ;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: Timeout\n");
+#endif /* DEBUG */
+ return RC_RTN_MSG_REPLY_TIMEOUT;
+ }
+ }
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: after time out\n", \
+ "p32[0] (IpAddr) 0x%08.8ulx, p32[1] (IPmask) 0x%08.8ulx\n", p32[0], p32[1]);
+#endif /* DEBUG */
+
+ /* send IP and mask to user's space */
+ *pIpAddr = p32[0];
+ *pNetMask = p32[1];
+
+
+#ifdef DEBUG
+ kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
+#endif /* DEBUG */
+
+ return RC_RTN_NO_ERROR;
+}
+
+/*
+** /////////////////////////////////////////////////////////////////////////
+** /////////////////////////////////////////////////////////////////////////
+**
+** local functions
+**
+** /////////////////////////////////////////////////////////////////////////
+** /////////////////////////////////////////////////////////////////////////
+*/
+
+/*
+** =========================================================================
+** SendI2OOutboundQInitMsg()
+**
+** =========================================================================
+*/
+static int
+SendI2OOutboundQInitMsg(PPAB pPab)
+{
+ U32 msgOffset, timeout, phyOutQFrames, i;
+ volatile PU32 pMsg;
+ volatile PU32 p32;
+
+
+
+ msgOffset = pPab->p_atu->InQueue;
+
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+#ifdef DEBUG
+ kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
+#endif /* DEBUG */
+
+ pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
+ pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = 0x106; /* transaction context */
+ pMsg[4] = 4096; /* Host page frame size */
+ pMsg[5] = MSG_FRAME_SIZE << 16 | 0x80; /* outbound msg frame size and Initcode */
+ pMsg[6] = 0xD0000004; /* simple sgl element LE, EOB */
+ /* phys address to return status - area right after PAB */
+ pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+
+ /* virual pointer to return buffer - clear first two dwords */
+ p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0;
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+ /* wait for response */
+ timeout = 100000;
+ while(1)
+ {
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0])
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout wait for InitOutQ InPrgress status from IOP\n");
+#endif /* DEBUG */
+ return RC_RTN_NO_I2O_STATUS;
+ }
+ }
+
+ timeout = 100000;
+ while(1)
+ {
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE)
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout wait for InitOutQ Complete status from IOP\n");
+#endif /* DEBUG */
+ return RC_RTN_NO_I2O_STATUS;
+ }
+ }
+
+ /* load PCI outbound free Q with MF physical addresses */
+ phyOutQFrames = pPab->outMsgBlockPhyAddr;
+
+ for (i = 0; i < NMBR_MSG_FRAMES; i++)
+ {
+ pPab->p_atu->OutQueue = phyOutQFrames;
+ phyOutQFrames += MSG_FRAME_SIZE;
+ }
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** GetI2OStatus()
+**
+** Send StatusGet Msg, wait for results return directly to buffer.
+**
+** =========================================================================
+*/
+static int
+GetI2OStatus(PPAB pPab)
+{
+ U32 msgOffset, timeout;
+ PU32 pMsg;
+ volatile PU32 p32;
+
+
+ msgOffset = pPab->p_atu->InQueue;
+#ifdef DEBUG
+ printk("GetI2OStatus: msg offset = 0x%x\n", msgOffset);
+#endif /* DEBUG */
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("GetI2OStatus(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+ pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_EXEC_STATUS_GET << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = 0; /* universal context */
+ pMsg[3] = 0; /* universal context */
+ pMsg[4] = 0; /* universal context */
+ pMsg[5] = 0; /* universal context */
+ /* phys address to return status - area right after PAB */
+ pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB);
+ pMsg[7] = 0;
+ pMsg[8] = 88; /* return 88 bytes */
+
+ /* virual pointer to return buffer - clear first two dwords */
+ p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+ p32[0] = 0;
+ p32[1] = 0;
+
+#ifdef DEBUG
+ kprintf("GetI2OStatus - pMsg:0x%08.8ulx, msgOffset:0x%08.8ulx, [1]:0x%08.8ulx, [6]:0x%08.8ulx\n",
+ pMsg, msgOffset, pMsg[1], pMsg[6]);
+#endif /* DEBUG */
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+#ifdef DEBUG
+ kprintf("Return status to p32 = 0x%08.8ulx\n", p32);
+#endif /* DEBUG */
+
+ /* wait for response */
+ timeout = 1000000;
+ while(1)
+ {
+ int i;
+
+ for (i = 0; i < 1000; i++) /* please don't hog the bus!!! */
+ ;
+
+ if (p32[0] && p32[1])
+ break;
+
+ if (!timeout--)
+ {
+#ifdef DEBUG
+ kprintf("Timeout waiting for status from IOP\n");
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
+#endif /* DEBUG */
+ return RC_RTN_NO_I2O_STATUS;
+ }
+ }
+
+#ifdef DEBUG
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+ kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
+#endif /* DEBUG */
+ /* get IOP state */
+ pPab->IOPState = ((volatile PU8)p32)[10];
+ pPab->InboundMFrameSize = ((volatile PU16)p32)[6];
+
+#ifdef DEBUG
+ kprintf("IOP state 0x%02.2x InFrameSize = 0x%04.4x\n",
+ pPab->IOPState, pPab->InboundMFrameSize);
+#endif /* DEBUG */
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** SendEnableSysMsg()
+**
+**
+** =========================================================================
+*/
+static int
+SendEnableSysMsg(PPAB pPab)
+{
+ U32 msgOffset; // timeout;
+ volatile PU32 pMsg;
+
+ msgOffset = pPab->p_atu->InQueue;
+
+ if (msgOffset == 0xFFFFFFFF)
+ {
+#ifdef DEBUG
+ kprintf("SendEnableSysMsg(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+ return RC_RTN_FREE_Q_EMPTY;
+ }
+
+ /* calc virual address of msg - virual already mapped to physical */
+ pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+#ifdef DEBUG
+ kprintf("SendEnableSysMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
+#endif /* DEBUG */
+
+ pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+ pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
+ pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+ pMsg[3] = 0x110; /* transaction context */
+ pMsg[4] = 0x50657465; /* RedCreek Private */
+
+ /* post to Inbound Post Q */
+ pPab->p_atu->InQueue = msgOffset;
+
+ return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** FillI2OMsgFromTCB()
+**
+** inputs pMsgU32 - virual pointer (mapped to physical) of message frame
+** pXmitCntrlBlock - pointer to caller buffer control block.
+**
+** fills in LAN SGL after Transaction Control Word or Bucket Count.
+** =========================================================================
+*/
+static int
+FillI2OMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
+{
+ unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
+ PU32 pTCB, pMsg;
+
+ /* SGL element flags */
+#define EOB 0x40000000
+#define LE 0x80000000
+#define SIMPLE_SGL 0x10000000
+#define BC_PRESENT 0x01000000
+
+ pTCB = (PU32)pTransCtrlBlock;
+ pMsg = pMsgFrame;
+ nmbrDwords = 0;
+
+#ifdef DEBUG
+ kprintf("FillI2OMsgSGLFromTCBX\n");
+ kprintf("TCB 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+ pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
+ kprintf("pTCB 0x%08.8ulx, pMsg 0x%08.8ulx\n", pTCB, pMsg);
+#endif /* DEBUG */
+
+ nmbrBuffers = *pTCB++;
+
+ if (!nmbrBuffers)
+ {
+ return -1;
+ }
+
+ do
+ {
+ context = *pTCB++; /* buffer tag (context) */
+ nmbrSeg = *pTCB++; /* number of segments */
+
+ if (!nmbrSeg)
+ {
+ return -1;
+ }
+
+ flags = SIMPLE_SGL | BC_PRESENT;
+
+ if (1 == nmbrSeg)
+ {
+ flags |= EOB;
+
+ if (1 == nmbrBuffers)
+ flags |= LE;
+ }
+
+ /* 1st SGL buffer element has context */
+ pMsg[0] = pTCB[0] | flags ; /* send over count (segment size) */
+ pMsg[1] = context;
+ pMsg[2] = pTCB[1]; /* send buffer segment physical address */
+ nmbrDwords += 3;
+ pMsg += 3;
+ pTCB += 2;
+
+
+ if (--nmbrSeg)
+ {
+ do
+ {
+ flags = SIMPLE_SGL;
+
+ if (1 == nmbrSeg)
+ {
+ flags |= EOB;
+
+ if (1 == nmbrBuffers)
+ flags |= LE;
+ }
+
+ pMsg[0] = pTCB[0] | flags; /* send over count */
+ pMsg[1] = pTCB[1]; /* send buffer segment physical address */
+ nmbrDwords += 2;
+ pTCB += 2;
+ pMsg += 2;
+
+ } while (--nmbrSeg);
+ }
+
+ } while (--nmbrBuffers);
+
+ return nmbrDwords;
+}
+
+
+/*
+** =========================================================================
+** ProcessOutboundI2OMsg()
+**
+** process I2O reply message
+** * change to msg structure *
+** =========================================================================
+*/
+static void
+ProcessOutboundI2OMsg(PPAB pPab, U32 phyAddrMsg)
+{
+ PU8 p8Msg;
+ PU32 p32;
+ // U16 count;
+
+
+ p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+ p32 = (PU32)p8Msg;
+
+#ifdef DEBUG
+ kprintf("VXD: ProcessOutboundI2OMsg - pPab 0x%08.8ulx, phyAdr 0x%08.8ulx, linAdr 0x%08.8ulx\n", pPab, phyAddrMsg, p8Msg);
+ kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+#endif /* DEBUG */
+
+ if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS)
+ {
+#ifdef DEBUG
+ kprintf("Message reply status not success\n");
+#endif /* DEBUG */
+ return;
+ }
+
+ switch (p8Msg[7] ) /* function code byte */
+ {
+ case I2O_EXEC_SYS_TAB_SET:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_SYS_TAB_SET reply\n");
+#endif /* DEBUG */
+ break;
+
+ case I2O_EXEC_HRT_GET:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_HRT_GET reply\n");
+#endif /* DEBUG */
+ break;
+
+ case I2O_EXEC_LCT_NOTIFY:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_LCT_NOTIFY reply\n");
+#endif /* DEBUG */
+ break;
+
+ case I2O_EXEC_SYS_ENABLE:
+ msgFlag = 1;
+#ifdef DEBUG
+ kprintf("Received I2O_EXEC_SYS_ENABLE reply\n");
+#endif /* DEBUG */
+ break;
+
+ default:
+#ifdef DEBUG
+ kprintf("Received UNKNOWN reply\n");
+#endif /* DEBUG */
+ break;
+ }
+}
diff --git a/drivers/net/rclanmtl.h b/drivers/net/rclanmtl.h
new file mode 100644
index 000000000..2521b1cee
--- /dev/null
+++ b/drivers/net/rclanmtl.h
@@ -0,0 +1,637 @@
+/*
+** *************************************************************************
+**
+**
+** R C L A N M T L . H $Revision: 5 $
+**
+**
+** RedCreek I2O LAN Message Transport Layer header file.
+**
+** ---------------------------------------------------------------------
+** --- Copyright (c) 1997-1999, RedCreek Communications Inc. ---
+** --- All rights reserved. ---
+** ---------------------------------------------------------------------
+**
+** File Description:
+**
+** Header file for host I2O (Intelligent I/O) LAN message transport layer
+** API and data types.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** *************************************************************************
+*/
+
+#ifndef RCLANMTL_H
+#define RCLANMTL_H
+
+/* Linux specific includes */
+#define kprintf printk
+#ifdef RC_LINUX_MODULE /* linux modules need non-library version of string functions */
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+/* PCI/45 Configuration space values */
+#define RC_PCI45_VENDOR_ID 0x4916
+#define RC_PCI45_DEVICE_ID 0x1960
+
+
+ /* RedCreek API function return values */
+#define RC_RTN_NO_ERROR 0
+#define RC_RTN_I2O_NOT_INIT 1
+#define RC_RTN_FREE_Q_EMPTY 2
+#define RC_RTN_TCB_ERROR 3
+#define RC_RTN_TRANSACTION_ERROR 4
+#define RC_RTN_ADAPTER_ALREADY_INIT 5
+#define RC_RTN_MALLOC_ERROR 6
+#define RC_RTN_ADPTR_NOT_REGISTERED 7
+#define RC_RTN_MSG_REPLY_TIMEOUT 8
+#define RC_RTN_NO_I2O_STATUS 9
+#define RC_RTN_NO_FIRM_VER 10
+#define RC_RTN_NO_LINK_SPEED 11
+
+/* Driver capability flags */
+#define WARM_REBOOT_CAPABLE 0x01
+
+ /* scalar data types */
+typedef unsigned char U8;
+typedef unsigned char* PU8;
+typedef unsigned short U16;
+typedef unsigned short* PU16;
+typedef unsigned long U32;
+typedef unsigned long* PU32;
+typedef unsigned long BF;
+typedef int RC_RETURN;
+
+
+ /*
+ ** type PFNWAITCALLBACK
+ **
+ ** pointer to void function - type used for WaitCallback in some functions
+ */
+typedef void (*PFNWAITCALLBACK)(void); /* void argument avoids compiler complaint */
+
+ /*
+ ** type PFNTXCALLBACK
+ **
+ ** Pointer to user's transmit callback function. This user function is
+ ** called from RCProcI2OMsgQ() when packet have been transmitted from buffers
+ ** given in the RCI2OSendPacket() function. BufferContext is a pointer to
+ ** an array of 32 bit context values. These are the values the user assigned
+ ** and passed in the TCB to the RCI2OSendPacket() function. PcktCount
+ ** indicates the number of buffer context values in the BufferContext[] array.
+ ** The User's TransmitCallbackFunction should recover (put back in free queue)
+ ** the packet buffers associated with the buffer context values.
+ */
+typedef void (*PFNTXCALLBACK)(U32 Status,
+ U16 PcktCount,
+ PU32 BufferContext,
+ U16 AdaterID);
+
+ /*
+ ** type PFNRXCALLBACK
+ **
+ ** Pointer to user's receive callback function. This user function
+ ** is called from RCProcI2OMsgQ() when packets have been received into
+ ** previously posted packet buffers throught the RCPostRecvBuffers() function.
+ ** The received callback function should process the Packet Descriptor Block
+ ** pointed to by PacketDescBlock. See Packet Decription Block below.
+ */
+typedef void (*PFNRXCALLBACK)(U32 Status,
+ U8 PktCount,
+ U32 BucketsRemain,
+ PU32 PacketDescBlock,
+ U16 AdapterID);
+
+ /*
+ ** type PFNCALLBACK
+ **
+ ** Pointer to user's generic callback function. This user function
+ ** can be passed to LANReset or LANShutdown and is called when the
+ ** the reset or shutdown is complete.
+ ** Param1 and Param2 are invalid for LANReset and LANShutdown.
+ */
+typedef void (*PFNCALLBACK)(U32 Status,
+ U32 Param1,
+ U32 Param2,
+ U16 AdapterID);
+
+/*
+** Status - Transmit and Receive callback status word
+**
+** A 32 bit Status is returned to the TX and RX callback functions. This value
+** contains both the reply status and the detailed status as follows:
+**
+** 32 24 16 0
+** +------+------+------------+
+** | Reply| | Detailed |
+** |Status| 0 | Status |
+** +------+------+------------+
+**
+** Reply Status and Detailed Status of zero indicates No Errors.
+*/
+ /* reply message status defines */
+#define I2O_REPLY_STATUS_SUCCESS 0x00
+#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
+#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A
+
+
+/* DetailedStatusCode defines */
+#define I2O_LAN_DSC_SUCCESS 0x0000
+#define I2O_LAN_DSC_DEVICE_FAILURE 0x0001
+#define I2O_LAN_DSC_DESTINATION_NOT_FOUND 0x0002
+#define I2O_LAN_DSC_TRANSMIT_ERROR 0x0003
+#define I2O_LAN_DSC_TRANSMIT_ABORTED 0x0004
+#define I2O_LAN_DSC_RECEIVE_ERROR 0x0005
+#define I2O_LAN_DSC_RECEIVE_ABORTED 0x0006
+#define I2O_LAN_DSC_DMA_ERROR 0x0007
+#define I2O_LAN_DSC_BAD_PACKET_DETECTED 0x0008
+#define I2O_LAN_DSC_OUT_OF_MEMORY 0x0009
+#define I2O_LAN_DSC_BUCKET_OVERRUN 0x000A
+#define I2O_LAN_DSC_IOP_INTERNAL_ERROR 0x000B
+#define I2O_LAN_DSC_CANCELED 0x000C
+#define I2O_LAN_DSC_INVALID_TRANSACTION_CONTEXT 0x000D
+#define I2O_LAN_DSC_DESTINATION_ADDRESS_DETECTED 0x000E
+#define I2O_LAN_DSC_DESTINATION_ADDRESS_OMITTED 0x000F
+#define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED 0x0010
+
+
+/*
+** Packet Description Block (Received packets)
+**
+** A pointer to this block structure is returned to the ReceiveCallback
+** function. It contains the list of packet buffers which have either been
+** filled with a packet or returned to host due to a LANReset function.
+** Currently there will only be one packet per receive bucket (buffer) posted.
+**
+** 32 24 0
+** +-----------------------+ -\
+** | Buffer 1 Context | \
+** +-----------------------+ \
+** | 0xC0000000 | / First Bucket Descriptor
+** +-----+-----------------+ /
+** | 0 | packet 1 length | /
+** +-----------------------+ -\
+** | Buffer 2 Context | \
+** +-----------------------+ \
+** | 0xC0000000 | / Second Bucket Descriptor
+** +-----+-----------------+ /
+** | 0 | packet 2 length | /
+** +-----+-----------------+ -
+** | ... | ----- more bucket descriptors
+** +-----------------------+ -\
+** | Buffer n Context | \
+** +-----------------------+ \
+** | 0xC0000000 | / Last Bucket Descriptor
+** +-----+-----------------+ /
+** | 0 | packet n length | /
+** +-----+-----------------+ -
+**
+** Buffer Context values are those given to adapter in the TCB on calls to
+** RCPostRecvBuffers().
+**
+*/
+
+
+
+/*
+** Transaction Control Block (TCB) structure
+**
+** A structure like this is filled in by the user and passed by reference to
+** RCI2OSendPacket() and RCPostRecvBuffers() functions. Minimum size is five
+** 32-bit words for one buffer with one segment descriptor.
+** MAX_NMBR_POST_BUFFERS_PER_MSG defines the maximum single segment buffers
+** that can be described in a given TCB.
+**
+** 32 0
+** +-----------------------+
+** | Buffer Count | Number of buffers in the TCB
+** +-----------------------+
+** | Buffer 1 Context | first buffer reference
+** +-----------------------+
+** | Buffer 1 Seg Count | number of segments in buffer
+** +-----------------------+
+** | Buffer 1 Seg Desc 1 | first segment descriptor (size, physical address)
+** +-----------------------+
+** | ... | more segment descriptors (size, physical address)
+** +-----------------------+
+** | Buffer 1 Seg Desc n | last segment descriptor (size, physical address)
+** +-----------------------+
+** | Buffer 2 Context | second buffer reference
+** +-----------------------+
+** | Buffer 2 Seg Count | number of segments in buffer
+** +-----------------------+
+** | Buffer 2 Seg Desc 1 | segment descriptor (size, physical address)
+** +-----------------------+
+** | ... | more segment descriptors (size, physical address)
+** +-----------------------+
+** | Buffer 2 Seg Desc n |
+** +-----------------------+
+** | ... | more buffer descriptor blocks ...
+** +-----------------------+
+** | Buffer n Context |
+** +-----------------------+
+** | Buffer n Seg Count |
+** +-----------------------+
+** | Buffer n Seg Desc 1 |
+** +-----------------------+
+** | ... |
+** +-----------------------+
+** | Buffer n Seg Desc n |
+** +-----------------------+
+**
+**
+** A TCB for one contigous packet buffer would look like the following:
+**
+** 32 0
+** +-----------------------+
+** | 1 | one buffer in the TCB
+** +-----------------------+
+** | <user's Context> | user's buffer reference
+** +-----------------------+
+** | 1 | one segment buffer
+** +-----------------------+ _
+** | <buffer size> | size \
+** +-----------------------+ \ segment descriptor
+** | <physical address> | physical address of buffer /
+** +-----------------------+ _/
+**
+*/
+
+ /* Buffer Segment Descriptor */
+typedef struct
+{
+ U32 size;
+ U32 phyAddress;
+}
+ BSD, *PBSD;
+
+typedef PU32 PRCTCB;
+/*
+** -------------------------------------------------------------------------
+** Exported functions comprising the API to the LAN I2O message transport layer
+** -------------------------------------------------------------------------
+*/
+
+
+ /*
+ ** InitRCI2OMsgLayer()
+ **
+ ** Called once prior to using the I2O LAN message transport layer. User
+ ** provides both the physical and virual address of a locked page buffer
+ ** that is used as a private buffer for the RedCreek I2O message
+ ** transport layer. This buffer must be a contigous memory block of a
+ ** minimum of 16K bytes and long word aligned. The user also must provide
+ ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
+ ** system. The user provided value AdapterID is a zero based index of the
+ ** Ravlin 45/PCI adapter. This interface number is used in all subsequent API
+ ** calls to identify which adpapter for which the function is intended.
+ ** Up to sixteen interfaces are supported with this API.
+ **
+ ** Inputs: AdapterID - interface number from 0 to 15
+ ** pciBaseAddr - virual base address of PCI (set by BIOS)
+ ** p_msgbuf - virual address to private message block (min. 16K)
+ ** p_phymsgbuf - physical address of private message block
+ ** TransmitCallbackFunction - address of user's TX callback function
+ ** ReceiveCallbackFunction - address of user's RX callback function
+ **
+ */
+RC_RETURN RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr,
+ PU8 p_msgbuf, PU8 p_phymsgbuf,
+ PFNTXCALLBACK TransmitCallbackFunction,
+ PFNRXCALLBACK ReceiveCallbackFunction,
+ PFNCALLBACK RebootCallbackFunction);
+
+ /*
+ ** RCSetRavlinIPandMask()
+ **
+ ** Set the Ravlin 45/PCI cards IP address and network mask.
+ **
+ ** IP address and mask must be in network byte order.
+ ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+ ** 0x04030201 and 0x00FFFFFF on a little endian machine.
+ **
+ */
+RC_RETURN RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask);
+
+
+/*
+** =========================================================================
+** RCGetRavlinIPandMask()
+**
+** get the IP address and MASK from the card
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask,
+ PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCProcI2OMsgQ()
+ **
+ ** Called from user's polling loop or Interrupt Service Routine for a PCI
+ ** interrupt from the RedCreek PCI adapter. User responsible for determining
+ ** and hooking the PCI interrupt. This function will call the registered
+ ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
+ ** if a TX or RX transaction has completed.
+ */
+void RCProcI2OMsgQ(U16 AdapterID);
+
+
+ /*
+ ** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time
+ ** but can be disabled and re-enabled through these two function calls.
+ ** Packets will still be put into any posted recieved buffers and packets will
+ ** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts
+ ** will prevent hardware interrupt to host even though the outbound I2O msg
+ ** queue is not emtpy.
+ */
+RC_RETURN RCEnableI2OInterrupts(U16 adapterID);
+RC_RETURN RCDisableI2OInterrupts(U16 AdapterID);
+
+
+ /*
+ ** RCPostRecvBuffers()
+ **
+ ** Post user's page locked buffers for use by the PCI adapter to
+ ** return ethernet packets received from the LAN. Transaction Control Block,
+ ** provided by user, contains buffer descriptor(s) which includes a buffer
+ ** context number along with buffer size and physical address. See TCB above.
+ ** The buffer context and actual packet length are returned to the
+ ** ReceiveCallbackFunction when packets have been received. Buffers posted
+ ** to the RedCreek adapter are considered owned by the adapter until the
+ ** context is return to user through the ReceiveCallbackFunction.
+ */
+RC_RETURN RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransactionCtrlBlock);
+#define MAX_NMBR_POST_BUFFERS_PER_MSG 32
+
+ /*
+ ** RCI2OSendPacket()
+ **
+ ** Send user's ethernet packet from a locked page buffer.
+ ** Packet must have full MAC header, however without a CRC.
+ ** Initiator context is a user provided value that is returned
+ ** to the TransmitCallbackFunction when packet buffer is free.
+ ** Transmit buffer are considered owned by the adapter until context's
+ ** returned to user through the TransmitCallbackFunction.
+ */
+RC_RETURN RCI2OSendPacket(U16 AdapterID,
+ U32 context,
+ PRCTCB pTransactionCtrlBlock);
+
+
+ /* Ethernet Link Statistics structure */
+typedef struct tag_RC_link_stats
+{
+ U32 TX_good; /* good transmit frames */
+ U32 TX_maxcol; /* frames not TX due to MAX collisions */
+ U32 TX_latecol; /* frames not TX due to late collisions */
+ U32 TX_urun; /* frames not TX due to DMA underrun */
+ U32 TX_crs; /* frames TX with lost carrier sense */
+ U32 TX_def; /* frames deferred due to activity on link */
+ U32 TX_singlecol; /* frames TX with one and only on collision */
+ U32 TX_multcol; /* frames TX with more than one collision */
+ U32 TX_totcol; /* total collisions detected during TX */
+ U32 Rcv_good; /* good frames received */
+ U32 Rcv_CRCerr; /* frames RX and discarded with CRC errors */
+ U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
+ U32 Rcv_reserr; /* good frames discarded due to no RX buffer */
+ U32 Rcv_orun; /* RX frames lost due to FIFO overrun */
+ U32 Rcv_cdt; /* RX frames with collision during RX */
+ U32 Rcv_runt; /* RX frames shorter than 64 bytes */
+}
+ RCLINKSTATS, *P_RCLINKSTATS;
+
+ /*
+ ** RCGetLinkStatistics()
+ **
+ ** Returns link statistics in user's structure at address StatsReturnAddr
+ ** If given, not NULL, the function WaitCallback is called during the wait
+ ** loop while waiting for the adapter to respond.
+ */
+RC_RETURN RCGetLinkStatistics(U16 AdapterID,
+ P_RCLINKSTATS StatsReturnAddr,
+ PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCGetLinkStatus()
+ **
+ ** Return link status, up or down, to user's location addressed by ReturnAddr.
+ ** If given, not NULL, the function WaitCallback is called during the wait
+ ** loop while waiting for the adapter to respond.
+ */
+RC_RETURN RCGetLinkStatus(U16 AdapterID,
+ PU32 pReturnStatus,
+ PFNWAITCALLBACK WaitCallback);
+
+ /* Link Status defines - value returned in pReturnStatus */
+#define RC_LAN_LINK_STATUS_DOWN 0
+#define RC_LAN_LINK_STATUS_UP 1
+
+ /*
+ ** RCGetMAC()
+ **
+ ** Get the current MAC address assigned to user. RedCreek Ravlin 45/PCI
+ ** has two MAC addresses. One which is private to the PCI Card, and
+ ** another MAC which is given to the user as its link layer MAC address. The
+ ** adapter runs in promiscous mode because of the dual address requirement.
+ ** The MAC address is returned to the unsigned char array pointer to by mac.
+ */
+RC_RETURN RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCSetMAC()
+ **
+ ** Set a new user port MAC address. This address will be returned on
+ ** subsequent RCGetMAC() calls.
+ */
+RC_RETURN RCSetMAC(U16 AdapterID, PU8 mac);
+
+ /*
+ ** RCSetLinkSpeed()
+ **
+ ** set adapter's link speed based on given input code.
+ */
+RC_RETURN RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode);
+ /* Set link speed codes */
+#define LNK_SPD_AUTO_NEG_NWAY 0
+#define LNK_SPD_100MB_FULL 1
+#define LNK_SPD_100MB_HALF 2
+#define LNK_SPD_10MB_FULL 3
+#define LNK_SPD_10MB_HALF 4
+
+
+
+
+ /*
+ ** RCGetLinkSpeed()
+ **
+ ** Return link speed code.
+ */
+ /* Return link speed codes */
+#define LNK_SPD_UNKNOWN 0
+#define LNK_SPD_100MB_FULL 1
+#define LNK_SPD_100MB_HALF 2
+#define LNK_SPD_10MB_FULL 3
+#define LNK_SPD_10MB_HALF 4
+
+RC_RETURN
+RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
+/*
+** =========================================================================
+** RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/
+#define PROMISCUOUS_MODE_OFF 0
+#define PROMISCUOUS_MODE_ON 1
+RC_RETURN
+RCSetPromiscuousMode(U16 AdapterID, U16 Mode);
+/*
+** =========================================================================
+** RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+**
+** get promiscuous mode setting
+**
+** Possible return values placed in pMode:
+** 0 = promisuous mode not set
+** 1 = promisuous mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+
+/*
+** =========================================================================
+** RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+**
+** Defined values for Mode:
+** 0 - turn off promiscuous mode
+** 1 - turn on promiscuous mode
+**
+** =========================================================================
+*/
+#define BROADCAST_MODE_OFF 0
+#define BROADCAST_MODE_ON 1
+RC_RETURN
+RCSetBroadcastMode(U16 AdapterID, U16 Mode);
+/*
+** =========================================================================
+** RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+**
+** get broadcast mode setting
+**
+** Possible return values placed in pMode:
+** 0 = broadcast mode not set
+** 1 = broadcast mode is set
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+/*
+** =========================================================================
+** RCReportDriverCapability(U16 AdapterID, U32 capability)
+**
+** Currently defined bits:
+** WARM_REBOOT_CAPABLE 0x01
+**
+** =========================================================================
+*/
+RC_RETURN
+RCReportDriverCapability(U16 AdapterID, U32 capability);
+
+/*
+** RCGetFirmwareVer()
+**
+** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
+**
+** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
+*/
+RC_RETURN
+RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
+
+/*
+** ----------------------------------------------
+** LAN adapter Reset and Shutdown functions
+** ----------------------------------------------
+*/
+ /* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */
+#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS 0x0001
+#define RC_RESOURCE_RETURN_PEND_TX_BUFFERS 0x0002
+
+ /*
+ ** RCResetLANCard()
+ **
+ ** Reset LAN card operation. Causes a software reset of the ethernet
+ ** controller and restarts the command and receive units. Depending on
+ ** the ResourceFlags given, the buffers are either returned to the
+ ** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
+ ** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
+ ** posted after issuing this) OR the buffers are kept and reused by
+ ** the ethernet controller. If CallbackFunction is not NULL, the function
+ ** will be called when the reset is complete. If the CallbackFunction is
+ ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
+ ** to complete (please disable I2O interrupts during this method).
+ ** Any outstanding transmit or receive buffers that are complete will be
+ ** returned via the normal reply messages before the requested resource
+ ** buffers are returned.
+ ** A call to RCPostRecvBuffers() is needed to return the ethernet to full
+ ** operation if the receive buffers were returned during LANReset.
+ ** Note: The IOP status is not affected by a LAN reset.
+ */
+RC_RETURN RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+
+ /*
+ ** RCShutdownLANCard()
+ **
+ ** Shutdown LAN card operation and put into an idle (suspended) state.
+ ** The LAN card is restarted with RCResetLANCard() function.
+ ** Depending on the ResourceFlags given, the buffers are either returned
+ ** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER
+ ** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
+ ** posted after issuing this) OR the buffers are kept and reused by
+ ** the ethernet controller. If CallbackFunction is not NULL, the function
+ ** will be called when the reset is complete. If the CallbackFunction is
+ ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
+ ** to complete (please disable I2O interrupts during this method).
+ ** Any outstanding transmit or receive buffers that are complete will be
+ ** returned via the normal reply messages before the requested resource
+ ** buffers are returned.
+ ** Note: The IOP status is not affected by a LAN shutdown.
+ */
+RC_RETURN
+RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+ /*
+ ** RCResetIOP();
+ ** Initializes IOPState to I2O_IOP_STATE_RESET.
+ ** Stops access to outbound message Q.
+ ** Discards any outstanding transmit or posted receive buffers.
+ ** Clears outbound message Q.
+ */
+RC_RETURN
+RCResetIOP(U16 AdapterID);
+
+#endif /* RCLANMTL_H */
diff --git a/drivers/net/rcpci45.c b/drivers/net/rcpci45.c
new file mode 100644
index 000000000..2c5a070ee
--- /dev/null
+++ b/drivers/net/rcpci45.c
@@ -0,0 +1,1419 @@
+/*
+** RCpci45.c
+**
+**
+**
+** ---------------------------------------------------------------------
+** --- Copyright (c) 1998, 1999, RedCreek Communications Inc. ---
+** --- All rights reserved. ---
+** ---------------------------------------------------------------------
+**
+** Written by Pete Popov and Brian Moyle.
+**
+** Known Problems
+**
+** None known at this time.
+**
+** TODO:
+** -Get rid of the wait loops in the API and replace them
+** with system independent delays ...something like
+** "delayms(2)". However, under normal circumstances, the
+** delays are very short so they're not a problem.
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the 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.
+**
+**
+** Pete Popov, January 11,99: Fixed a couple of 2.1.x problems
+** (virt_to_bus() not called), tested it under 2.2pre5, and added a
+** #define to enable the use of the same file for both, the 2.0.x kernels
+** as well as the 2.1.x.
+**
+** Ported to 2.1.x by Alan Cox 1998/12/9.
+**
+***************************************************************************/
+
+static char *version =
+"RedCreek Communications PCI linux driver version 2.00\n";
+
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <linux/timer.h>
+#include <asm/irq.h> /* For NR_IRQS only. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#if LINUX_VERSION_CODE >= 0x020100
+#define LINUX_2_1
+#endif
+
+#ifdef LINUX_2_1
+#include <asm/uaccess.h>
+#endif
+
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+
+#define RC_LINUX_MODULE
+#include "rclanmtl.h"
+#include "rcif.h"
+
+#define RUN_AT(x) (jiffies + (x))
+
+#define NEW_MULTICAST
+#include <linux/delay.h>
+
+#ifndef LINUX_2_1
+#define ioremap vremap
+#define iounmap vfree
+#endif
+
+/* PCI/45 Configuration space values */
+#define RC_PCI45_VENDOR_ID 0x4916
+#define RC_PCI45_DEVICE_ID 0x1960
+
+#define MAX_ETHER_SIZE 1520
+#define MAX_NMBR_RCV_BUFFERS 96
+#define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16
+#define BD_SIZE 3 /* Bucket Descriptor size */
+#define BD_LEN_OFFSET 2 /* Bucket Descriptor offset to length field */
+
+
+/* RedCreek LAN device Target ID */
+#define RC_LAN_TARGET_ID 0x10
+/* RedCreek's OSM default LAN receive Initiator */
+#define DEFAULT_RECV_INIT_CONTEXT 0xA17
+
+
+static U32 DriverControlWord = 0;
+
+static void rc_timer(unsigned long);
+
+/*
+ * Driver Private Area, DPA.
+ */
+typedef struct
+{
+
+ /*
+ * pointer to the device structure which is part
+ * of the interface to the Linux kernel.
+ */
+ struct device *dev;
+
+ char devname[8]; /* "ethN" string */
+ U8 id; /* the AdapterID */
+ U32 pci_addr; /* the pci address of the adapter */
+ U32 bus;
+ U32 function;
+ struct timer_list timer; /* timer */
+ struct enet_statistics stats; /* the statistics structure */
+ struct device *next; /* points to the next RC adapter */
+ unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
+ unsigned char shutdown;
+ unsigned char reboot;
+ unsigned char nexus;
+ PU8 PLanApiPA; /* Pointer to Lan Api Private Area */
+
+}
+DPA, *PDPA;
+
+#define MAX_ADAPTERS 32
+
+static PDPA PCIAdapters[MAX_ADAPTERS] =
+{
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+static int RCscan(void);
+static struct device
+*RCfound_device(struct device *, int, int, int, int, int, int);
+
+static int RCprobe1(struct device *);
+static int RCopen(struct device *);
+static int RC_xmit_packet(struct sk_buff *, struct device *);
+static void RCinterrupt(int, void *, struct pt_regs *);
+static int RCclose(struct device *dev);
+static struct enet_statistics *RCget_stats(struct device *);
+static int RCioctl(struct device *, struct ifreq *, int);
+static int RCconfig(struct device *, struct ifmap *);
+static void RCxmit_callback(U32, U16, PU32, U16);
+static void RCrecv_callback(U32, U8, U32, PU32, U16);
+static void RCreset_callback(U32, U32, U32, U16);
+static void RCreboot_callback(U32, U32, U32, U16);
+static int RC_allocate_and_post_buffers(struct device *, int);
+
+
+/* A list of all installed RC devices, for removing the driver module. */
+static struct device *root_RCdev = NULL;
+
+#ifdef MODULE
+int init_module(void)
+#else
+int rcpci_probe(struct netdevice *dev)
+#endif
+{
+ int cards_found;
+
+ printk(version);
+
+ root_RCdev = NULL;
+ cards_found = RCscan();
+#ifdef MODULE
+ return cards_found ? 0 : -ENODEV;
+#else
+ return -1;
+#endif
+}
+
+static int RCscan()
+{
+ int cards_found = 0;
+ struct device *dev = 0;
+
+ if (pcibios_present())
+ {
+ static int pci_index = 0;
+ unsigned char pci_bus, pci_device_fn;
+ int scan_status;
+ int board_index = 0;
+
+ for (;pci_index < 0xff; pci_index++)
+ {
+ unsigned char pci_irq_line;
+ unsigned short pci_command, vendor, device, class;
+ unsigned int pci_ioaddr;
+
+
+ scan_status =
+ (pcibios_find_device (RC_PCI45_VENDOR_ID,
+ RC_PCI45_DEVICE_ID,
+ pci_index,
+ &pci_bus,
+ &pci_device_fn));
+#ifdef RCDEBUG
+ printk("rc scan_status = 0x%X\n", scan_status);
+#endif
+ if (scan_status != PCIBIOS_SUCCESSFUL)
+ break;
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_DEVICE_ID, &device);
+ pcibios_read_config_byte(pci_bus,
+ pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ pcibios_read_config_dword(pci_bus,
+ pci_device_fn,
+ PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_CLASS_DEVICE, &class);
+
+ pci_ioaddr &= ~0xf;
+
+#ifdef RCDEBUG
+ printk("rc: Found RedCreek PCI adapter\n");
+ printk("rc: pci class = 0x%x 0x%x \n", class, class>>8);
+ printk("rc: pci_bus = %d, pci_device_fn = %d\n", pci_bus, pci_device_fn);
+ printk("rc: pci_irq_line = 0x%x \n", pci_irq_line);
+ printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr);
+#endif
+
+#if 1
+ if (check_region(pci_ioaddr, 2*32768))
+ {
+ printk("rc: check_region failed\n");
+ continue;
+ }
+ else
+ {
+ printk("rc: check_region passed\n");
+ }
+#endif
+
+ /*
+ * Get and check the bus-master and latency values.
+ * Some PCI BIOSes fail to set the master-enable bit.
+ */
+
+ pcibios_read_config_word(pci_bus,
+ pci_device_fn,
+ PCI_COMMAND,
+ &pci_command);
+ if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+ printk("rc: PCI Master Bit has not been set!\n");
+
+ pci_command |= PCI_COMMAND_MASTER;
+ pcibios_write_config_word(pci_bus,
+ pci_device_fn,
+ PCI_COMMAND,
+ pci_command);
+ }
+ if ( ! (pci_command & PCI_COMMAND_MEMORY)) {
+ /*
+ * If the BIOS did not set the memory enable bit, what else
+ * did it not initialize? Skip this adapter.
+ */
+ printk("rc: Adapter %d, PCI Memory Bit has not been set!\n",
+ cards_found);
+ printk("rc: Bios problem? \n");
+ continue;
+ }
+
+ dev = RCfound_device(dev, pci_ioaddr, pci_irq_line,
+ pci_bus, pci_device_fn,
+ board_index++, cards_found);
+
+ if (dev) {
+ dev = 0;
+ cards_found++;
+ }
+ }
+ }
+ printk("rc: found %d cards \n", cards_found);
+ return cards_found;
+}
+
+static struct device *
+RCfound_device(struct device *dev, int memaddr, int irq,
+ int bus, int function, int product_index, int card_idx)
+{
+ int dev_size = 32768;
+ unsigned long *vaddr=0;
+ PDPA pDpa;
+ int init_status;
+
+ /*
+ * Allocate and fill new device structure.
+ * We need enough for struct device plus DPA plus the LAN API private
+ * area, which requires a minimum of 16KB. The top of the allocated
+ * area will be assigned to struct device; the next chunk will be
+ * assigned to DPA; and finally, the rest will be assigned to the
+ * the LAN API layer.
+ */
+ dev = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
+ memset(dev, 0, dev_size);
+#ifdef RCDEBUG
+ printk("rc: dev = 0x%08X\n", (uint)dev);
+#endif
+
+ /*
+ * dev->priv will point to the start of DPA.
+ */
+ dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
+ pDpa = dev->priv;
+ dev->name = pDpa->devname;
+
+ pDpa->dev = dev; /* this is just for easy reference */
+ pDpa->function = function;
+ pDpa->bus = bus;
+ pDpa->id = card_idx; /* the device number */
+ pDpa->pci_addr = memaddr;
+ PCIAdapters[card_idx] = pDpa;
+#ifdef RCDEBUG
+ printk("rc: pDpa = 0x%x, id = %d \n", (uint)pDpa, (uint)pDpa->id);
+#endif
+
+ /*
+ * Save the starting address of the LAN API private area. We'll
+ * pass that to RCInitI2OMsgLayer().
+ */
+ pDpa->PLanApiPA = (void *)(((long)pDpa + sizeof(DPA) + 0xff) & ~0xff);
+#ifdef RCDEBUG
+ printk("rc: pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
+#endif
+
+ /* The adapter is accessable through memory-access read/write, not
+ * I/O read/write. Thus, we need to map it to some virtual address
+ * area in order to access the registers are normal memory.
+ */
+ vaddr = (ulong *) ioremap (memaddr, 2*32768);
+#ifdef RCDEBUG
+ printk("rc: RCfound_device: 0x%x, priv = 0x%x, vaddr = 0x%x\n",
+ (uint)dev, (uint)dev->priv, (uint)vaddr);
+#endif
+ dev->base_addr = (unsigned long)vaddr;
+ dev->irq = irq;
+ dev->interrupt = 0;
+
+ /*
+ * Request a shared interrupt line.
+ */
+ if ( request_irq(dev->irq, (void *)RCinterrupt,
+ SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )
+ {
+ printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );
+ iounmap(vaddr);
+ kfree(dev);
+ return 0;
+ }
+
+ init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr,
+ pDpa->PLanApiPA, (PU8)virt_to_bus((void *)pDpa->PLanApiPA),
+ (PFNTXCALLBACK)RCxmit_callback,
+ (PFNRXCALLBACK)RCrecv_callback,
+ (PFNCALLBACK)RCreboot_callback);
+#ifdef RCDEBUG
+ printk("rc: I2O msg initted: status = 0x%x\n", init_status);
+#endif
+ if (init_status)
+ {
+ printk("rc: Unable to initialize msg layer\n");
+ free_irq(dev->irq, dev);
+ iounmap(vaddr);
+ kfree(dev);
+ return 0;
+ }
+ if (RCGetMAC(pDpa->id, dev->dev_addr, NULL))
+ {
+ printk("rc: Unable to get adapter MAC\n");
+ free_irq(dev->irq, dev);
+ iounmap(vaddr);
+ kfree(dev);
+ return 0;
+ }
+
+ DriverControlWord |= WARM_REBOOT_CAPABLE;
+ RCReportDriverCapability(pDpa->id, DriverControlWord);
+
+ dev->init = RCprobe1;
+ ether_setup(dev); /* linux kernel interface */
+
+ pDpa->next = root_RCdev;
+ root_RCdev = dev;
+
+ if (register_netdev(dev) != 0) /* linux kernel interface */
+ {
+ printk("rc: unable to register device \n");
+ free_irq(dev->irq, dev);
+ iounmap(vaddr);
+ kfree(dev);
+ return 0;
+ }
+ return dev;
+}
+
+static int RCprobe1(struct device *dev)
+{
+ dev->open = RCopen;
+ dev->hard_start_xmit = RC_xmit_packet;
+ dev->stop = RCclose;
+ dev->get_stats = RCget_stats;
+ dev->do_ioctl = RCioctl;
+ dev->set_config = RCconfig;
+ return 0;
+}
+
+static int
+RCopen(struct device *dev)
+{
+ int post_buffers = MAX_NMBR_RCV_BUFFERS;
+ PDPA pDpa = (PDPA) dev->priv;
+ int count = 0;
+ int requested = 0;
+
+#ifdef RCDEBUG
+ printk("rc: RCopen\n");
+#endif
+ RCEnableI2OInterrupts(pDpa->id);
+
+ if (pDpa->nexus)
+ {
+ /* This is not the first time RCopen is called. Thus,
+ * the interface was previously opened and later closed
+ * by RCclose(). RCclose() does a Shutdown; to wake up
+ * the adapter, a reset is mandatory before we can post
+ * receive buffers. However, if the adapter initiated
+ * a reboot while the interface was closed -- and interrupts
+ * were turned off -- we need will need to reinitialize
+ * the adapter, rather than simply waking it up.
+ */
+ printk("rc: Waking up adapter...\n");
+ RCResetLANCard(pDpa->id,0,0,0);
+ }
+ else
+ {
+ pDpa->nexus = 1;
+ }
+
+ while(post_buffers)
+ {
+ if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+ requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
+ else
+ requested = post_buffers;
+ count = RC_allocate_and_post_buffers(dev, requested);
+
+ if ( count < requested )
+ {
+ /*
+ * Check to see if we were able to post any buffers at all.
+ */
+ if (post_buffers == MAX_NMBR_RCV_BUFFERS)
+ {
+ printk("rc: Error RCopen: not able to allocate any buffers\r\n");
+ return(-ENOMEM);
+ }
+ printk("rc: Warning RCopen: not able to allocate all requested buffers\r\n");
+ break; /* we'll try to post more buffers later */
+ }
+ else
+ post_buffers -= count;
+ }
+ pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
+ pDpa->shutdown = 0; /* just in case */
+#ifdef RCDEBUG
+ printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
+#endif
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+RC_xmit_packet(struct sk_buff *skb, struct device *dev)
+{
+
+ PDPA pDpa = (PDPA) dev->priv;
+ singleTCB tcb;
+ psingleTCB ptcb = &tcb;
+ RC_RETURN status = 0;
+
+ if (dev->tbusy || pDpa->shutdown || pDpa->reboot)
+ {
+#ifdef RCDEBUG
+ printk("rc: RC_xmit_packet: tbusy!\n");
+#endif
+ return 1;
+ }
+
+ if ( skb->len <= 0 )
+ {
+ printk("RC_xmit_packet: skb->len less than 0!\n");
+ return 0;
+ }
+
+ /*
+ * The user is free to reuse the TCB after RCI2OSendPacket() returns, since
+ * the function copies the necessary info into its own private space. Thus,
+ * our TCB can be a local structure. The skb, on the other hand, will be
+ * freed up in our interrupt handler.
+ */
+ ptcb->bcount = 1;
+ /*
+ * we'll get the context when the adapter interrupts us to tell us that
+ * the transmision is done. At that time, we can free skb.
+ */
+ ptcb->b.context = (U32)skb;
+ ptcb->b.scount = 1;
+ ptcb->b.size = skb->len;
+ ptcb->b.addr = virt_to_bus((void *)skb->data);
+
+#ifdef RCDEBUG
+ printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n",
+ (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
+#endif
+ if ( (status = RCI2OSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb))
+ != RC_RTN_NO_ERROR)
+ {
+#ifdef RCDEBUG
+ printk("rc: RC send error 0x%x\n", (uint)status);
+#endif
+ dev->tbusy = 1;
+ return 1;
+ }
+ else
+ {
+ dev->trans_start = jiffies;
+ // dev->tbusy = 0;
+ }
+ /*
+ * That's it!
+ */
+ return 0;
+}
+
+/*
+ * RCxmit_callback()
+ *
+ * The transmit callback routine. It's called by RCProcI2OMsgQ()
+ * because the adapter is done with one or more transmit buffers and
+ * it's returning them to us, or we asked the adapter to return the
+ * outstanding transmit buffers by calling RCResetLANCard() with
+ * RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag.
+ * All we need to do is free the buffers.
+ */
+static void
+RCxmit_callback(U32 Status,
+ U16 PcktCount,
+ PU32 BufferContext,
+ U16 AdapterID)
+{
+ struct sk_buff *skb;
+ PDPA pDpa;
+ struct device *dev;
+
+ pDpa = PCIAdapters[AdapterID];
+ if (!pDpa)
+ {
+ printk("rc: Fatal error: xmit callback, !pDpa\n");
+ return;
+ }
+ dev = pDpa->dev;
+
+ // printk("xmit_callback: Status = 0x%x\n", (uint)Status);
+ if (Status != I2O_REPLY_STATUS_SUCCESS)
+ {
+ printk("rc: xmit_callback: Status = 0x%x\n", (uint)Status);
+ }
+#ifdef RCDEBUG
+ if (pDpa->shutdown || pDpa->reboot)
+ printk("rc: xmit callback: shutdown||reboot\n");
+#endif
+
+#ifdef RCDEBUG
+ printk("rc: xmit_callback: PcktCount = %d, BC = 0x%x\n",
+ (uint)PcktCount, (uint)BufferContext);
+#endif
+ while (PcktCount--)
+ {
+ skb = (struct sk_buff *)(BufferContext[0]);
+#ifdef RCDEBUG
+ printk("rc: skb = 0x%x\n", (uint)skb);
+#endif
+ BufferContext++;
+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else
+ dev_kfree_skb (skb, FREE_WRITE);
+#endif
+ }
+ dev->tbusy = 0;
+
+}
+
+static void
+RCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+{
+ PDPA pDpa;
+ struct device *dev;
+
+ pDpa = PCIAdapters[AdapterID];
+ dev = pDpa->dev;
+#ifdef RCDEBUG
+ printk("rc: RCreset_callback Status 0x%x\n", (uint)Status);
+#endif
+ /*
+ * Check to see why we were called.
+ */
+ if (pDpa->shutdown)
+ {
+ printk("rc: Shutting down interface\n");
+ pDpa->shutdown = 0;
+ pDpa->reboot = 0;
+ MOD_DEC_USE_COUNT;
+ }
+ else if (pDpa->reboot)
+ {
+ printk("rc: reboot, shutdown adapter\n");
+ /*
+ * We don't set any of the flags in RCShutdownLANCard()
+ * and we don't pass a callback routine to it.
+ * The adapter will have already initiated the reboot by
+ * the time the function returns.
+ */
+ RCDisableI2OInterrupts(pDpa->id);
+ RCShutdownLANCard(pDpa->id,0,0,0);
+ printk("rc: scheduling timer...\n");
+ init_timer(&pDpa->timer);
+ pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
+ pDpa->timer.data = (unsigned long)dev;
+ pDpa->timer.function = &rc_timer; /* timer handler */
+ add_timer(&pDpa->timer);
+ }
+
+
+
+}
+
+static void
+RCreboot_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+{
+ PDPA pDpa;
+
+ pDpa = PCIAdapters[AdapterID];
+#ifdef RCDEBUG
+ printk("rc: RCreboot: rcv buffers outstanding = %d\n",
+ (uint)pDpa->numOutRcvBuffers);
+#endif
+ if (pDpa->shutdown)
+ {
+ printk("rc: skipping reboot sequence -- shutdown already initiated\n");
+ return;
+ }
+ pDpa->reboot = 1;
+ /*
+ * OK, we reset the adapter and ask it to return all
+ * outstanding transmit buffers as well as the posted
+ * receive buffers. When the adapter is done returning
+ * those buffers, it will call our RCreset_callback()
+ * routine. In that routine, we'll call RCShutdownLANCard()
+ * to tell the adapter that it's OK to start the reboot and
+ * schedule a timer callback routine to execute 3 seconds
+ * later; this routine will reinitialize the adapter at that time.
+ */
+ RCResetLANCard(pDpa->id,
+ RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
+ RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
+ (PFNCALLBACK)RCreset_callback);
+}
+
+
+int broadcast_packet(unsigned char * address)
+{
+ int i;
+ for (i=0; i<6; i++)
+ if (address[i] != 0xff) return 0;
+
+ return 1;
+}
+
+/*
+ * RCrecv_callback()
+ *
+ * The receive packet callback routine. This is called by
+ * RCProcI2OMsgQ() after the adapter posts buffers which have been
+ * filled (one ethernet packet per buffer).
+ */
+static void
+RCrecv_callback(U32 Status,
+ U8 PktCount,
+ U32 BucketsRemain,
+ PU32 PacketDescBlock,
+ U16 AdapterID)
+{
+
+ U32 len, count;
+ PDPA pDpa;
+ struct sk_buff *skb;
+ struct device *dev;
+ singleTCB tcb;
+ psingleTCB ptcb = &tcb;
+
+
+ pDpa = PCIAdapters[AdapterID];
+ dev = pDpa->dev;
+
+ ptcb->bcount = 1;
+
+#ifdef RCDEBUG
+ printk("rc: RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
+ (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);
+#endif
+
+#ifdef RCDEBUG
+ if ((pDpa->shutdown || pDpa->reboot) && !Status)
+ printk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
+#endif
+
+ if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
+ {
+ /*
+ * Free whatever buffers the adapter returned, but don't
+ * pass them to the kernel.
+ */
+
+ if (!pDpa->shutdown && !pDpa->reboot)
+ printk("rc: RCrecv error: status = 0x%x\n", (uint)Status);
+ else
+ printk("rc: Returning %d buffers, status = 0x%x\n",
+ PktCount, (uint)Status);
+ /*
+ * TO DO: check the nature of the failure and put the adapter in
+ * failed mode if it's a hard failure. Send a reset to the adapter
+ * and free all outstanding memory.
+ */
+ if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
+ {
+#ifdef RCDEBUG
+ printk("RCrecv status ABORT NO DATA TRANSFER\n");
+#endif
+ }
+ /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */
+ if (PacketDescBlock)
+ {
+ while(PktCount--)
+ {
+ skb = (struct sk_buff *)PacketDescBlock[0];
+#ifndef LINUX_2_1
+ skb->free = 1;
+ skb->lock = 0;
+#endif
+#ifdef RCDEBUG
+ printk("free skb 0x%p\n", skb);
+#endif
+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else
+ dev_kfree_skb(skb, FREE_READ);
+#endif
+ pDpa->numOutRcvBuffers--;
+ PacketDescBlock += BD_SIZE; /* point to next context field */
+ }
+ }
+ return;
+ }
+ else
+ {
+ while(PktCount--)
+ {
+ skb = (struct sk_buff *)PacketDescBlock[0];
+#ifdef RCDEBUG
+ if (pDpa->shutdown)
+ printk("shutdown: skb=0x%x\n", (uint)skb);
+
+ printk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
+ (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2],
+ (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);
+#endif
+ if ( (memcmp(dev->dev_addr, skb->data, 6)) &&
+ (!broadcast_packet(skb->data)))
+ {
+ /*
+ * Re-post the buffer to the adapter. Since the adapter usually
+ * return 1 to 2 receive buffers at a time, it's not too inefficient
+ * post one buffer at a time but ... may be that should be
+ * optimized at some point.
+ */
+ ptcb->b.context = (U32)skb;
+ ptcb->b.scount = 1;
+ ptcb->b.size = MAX_ETHER_SIZE;
+ ptcb->b.addr = virt_to_bus((void *)skb->data);
+
+ if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
+ {
+ printk("rc: RCrecv_callback: post buffer failed!\n");
+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else
+ skb->free = 1;
+ dev_kfree_skb(skb, FREE_READ);
+#endif
+ }
+ else
+ {
+ pDpa->numOutRcvBuffers++;
+ }
+ }
+ else
+ {
+ len = PacketDescBlock[2];
+ skb->dev = dev;
+ skb_put( skb, len ); /* adjust length and tail */
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb); /* send the packet to the kernel */
+ dev->last_rx = jiffies;
+ }
+ pDpa->numOutRcvBuffers--;
+ PacketDescBlock += BD_SIZE; /* point to next context field */
+ }
+ }
+
+ /*
+ * Replenish the posted receive buffers.
+ * DO NOT replenish buffers if the driver has already
+ * initiated a reboot or shutdown!
+ */
+
+ if (!pDpa->shutdown && !pDpa->reboot)
+ {
+ count = RC_allocate_and_post_buffers(dev,
+ MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers);
+ pDpa->numOutRcvBuffers += count;
+ }
+
+}
+
+/*
+ * RCinterrupt()
+ *
+ * Interrupt handler.
+ * This routine sets up a couple of pointers and calls
+ * RCProcI2OMsgQ(), which in turn process the message and
+ * calls one of our callback functions.
+ */
+static void
+RCinterrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+ PDPA pDpa;
+ struct device *dev = (struct device *)(dev_id);
+
+ pDpa = (PDPA) (dev->priv);
+
+ if (pDpa->shutdown)
+ printk("rc: shutdown: service irq\n");
+
+#ifdef RCDEBUG
+ printk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n",
+ (uint)pDpa, (uint)dev, (uint)pDpa->id);
+ printk("dev = 0x%x\n", (uint)dev);
+#endif
+ if (dev->interrupt)
+ printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ dev->interrupt = 1;
+
+ RCProcI2OMsgQ(pDpa->id);
+ dev->interrupt = 0;
+
+ return;
+}
+
+#define REBOOT_REINIT_RETRY_LIMIT 10
+static void rc_timer(unsigned long data)
+{
+ struct device *dev = (struct device *)data;
+ PDPA pDpa = (PDPA) (dev->priv);
+ int init_status;
+ static int retry = 0;
+ int post_buffers = MAX_NMBR_RCV_BUFFERS;
+ int count = 0;
+ int requested = 0;
+
+ if (pDpa->reboot)
+ {
+
+ init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr,
+ pDpa->PLanApiPA, pDpa->PLanApiPA,
+ (PFNTXCALLBACK)RCxmit_callback,
+ (PFNRXCALLBACK)RCrecv_callback,
+ (PFNCALLBACK)RCreboot_callback);
+
+ switch(init_status)
+ {
+ case RC_RTN_NO_ERROR:
+
+ pDpa->reboot = 0;
+ pDpa->shutdown = 0; /* just in case */
+ RCReportDriverCapability(pDpa->id, DriverControlWord);
+ RCEnableI2OInterrupts(pDpa->id);
+
+ if (dev->flags & IFF_UP)
+ {
+ while(post_buffers)
+ {
+ if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+ requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
+ else
+ requested = post_buffers;
+ count = RC_allocate_and_post_buffers(dev, requested);
+ post_buffers -= count;
+ if ( count < requested )
+ break;
+ }
+ pDpa->numOutRcvBuffers =
+ MAX_NMBR_RCV_BUFFERS - post_buffers;
+ printk("rc: posted %d buffers \r\n",
+ (uint)pDpa->numOutRcvBuffers);
+ }
+ printk("rc: Initialization done.\n");
+ return;
+ case RC_RTN_FREE_Q_EMPTY:
+ retry++;
+ printk("rc: inbound free q emtpy\n");
+ break;
+ default:
+ retry++;
+ printk("rc: unexpected bad status after reboot\n");
+ break;
+ }
+
+ if (retry > REBOOT_REINIT_RETRY_LIMIT)
+ {
+ printk("rc: unable to reinitialize adapter after reboot\n");
+ printk("rc: decrementing driver and closing interface\n");
+ RCDisableI2OInterrupts(pDpa->id);
+ dev->flags &= ~IFF_UP;
+ MOD_DEC_USE_COUNT;
+ }
+ else
+ {
+ printk("rc: rescheduling timer...\n");
+ init_timer(&pDpa->timer);
+ pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
+ pDpa->timer.data = (unsigned long)dev;
+ pDpa->timer.function = &rc_timer; /* timer handler */
+ add_timer(&pDpa->timer);
+ }
+ }
+ else
+ {
+ printk("rc: timer??\n");
+ }
+}
+
+static int
+RCclose(struct device *dev)
+{
+
+ PDPA pDpa = (PDPA) dev->priv;
+
+#ifdef RCDEBUG
+ printk("rc: RCclose\r\n");
+#endif
+ if (pDpa->reboot)
+ {
+ printk("rc: skipping reset -- adapter already in reboot mode\n");
+ dev->flags &= ~IFF_UP;
+ pDpa->shutdown = 1;
+ return 0;
+ }
+#ifdef RCDEBUG
+ printk("rc: receive buffers outstanding: %d\n",
+ (uint)pDpa->numOutRcvBuffers);
+#endif
+
+ pDpa->shutdown = 1;
+
+ /*
+ * We can't allow the driver to be unloaded until the adapter returns
+ * all posted receive buffers. It doesn't hurt to tell the adapter
+ * to return all posted receive buffers and outstanding xmit buffers,
+ * even if there are none.
+ */
+
+ RCShutdownLANCard(pDpa->id,
+ RC_RESOURCE_RETURN_POSTED_RX_BUCKETS |
+ RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
+ (PFNCALLBACK)RCreset_callback);
+
+ dev->flags &= ~IFF_UP;
+ return 0;
+}
+
+static struct enet_statistics *
+RCget_stats(struct device *dev)
+{
+ RCLINKSTATS RCstats;
+
+ PDPA pDpa = dev->priv;
+
+ if (!pDpa)
+ {
+ printk("rc: RCget_stats: !pDpa\n");
+ return 0;
+ }
+ else if (!(dev->flags & IFF_UP))
+ {
+#ifdef RCDEBUG
+ printk("rc: RCget_stats: device down\n");
+#endif
+ return 0;
+ }
+
+ memset(&RCstats, 0, sizeof(RCLINKSTATS));
+ if ( (RCGetLinkStatistics(pDpa->id, &RCstats, (void *)0)) == RC_RTN_NO_ERROR )
+ {
+#ifdef RCDEBUG
+ printk("rc: TX_good 0x%x\n", (uint)RCstats.TX_good);
+ printk("rc: TX_maxcol 0x%x\n", (uint)RCstats.TX_maxcol);
+ printk("rc: TX_latecol 0x%x\n", (uint)RCstats.TX_latecol);
+ printk("rc: TX_urun 0x%x\n", (uint)RCstats.TX_urun);
+ printk("rc: TX_crs 0x%x\n", (uint)RCstats.TX_crs);
+ printk("rc: TX_def 0x%x\n", (uint)RCstats.TX_def);
+ printk("rc: TX_singlecol 0x%x\n", (uint)RCstats.TX_singlecol);
+ printk("rc: TX_multcol 0x%x\n", (uint)RCstats.TX_multcol);
+ printk("rc: TX_totcol 0x%x\n", (uint)RCstats.TX_totcol);
+
+ printk("rc: Rcv_good 0x%x\n", (uint)RCstats.Rcv_good);
+ printk("rc: Rcv_CRCerr 0x%x\n", (uint)RCstats.Rcv_CRCerr);
+ printk("rc: Rcv_alignerr 0x%x\n", (uint)RCstats.Rcv_alignerr);
+ printk("rc: Rcv_reserr 0x%x\n", (uint)RCstats.Rcv_reserr);
+ printk("rc: Rcv_orun 0x%x\n", (uint)RCstats.Rcv_orun);
+ printk("rc: Rcv_cdt 0x%x\n", (uint)RCstats.Rcv_cdt);
+ printk("rc: Rcv_runt 0x%x\n", (uint)RCstats.Rcv_runt);
+#endif
+
+ pDpa->stats.rx_packets = RCstats.Rcv_good; /* total packets received */
+ pDpa->stats.tx_packets = RCstats.TX_good; /* total packets transmitted */
+
+ pDpa->stats.rx_errors =
+ RCstats.Rcv_CRCerr +
+ RCstats.Rcv_alignerr +
+ RCstats.Rcv_reserr +
+ RCstats.Rcv_orun +
+ RCstats.Rcv_cdt +
+ RCstats.Rcv_runt; /* bad packets received */
+
+ pDpa->stats.tx_errors =
+ RCstats.TX_urun +
+ RCstats.TX_crs +
+ RCstats.TX_def +
+ RCstats.TX_totcol; /* packet transmit problems */
+
+ /*
+ * This needs improvement.
+ */
+ pDpa->stats.rx_dropped = 0; /* no space in linux buffers */
+ pDpa->stats.tx_dropped = 0; /* no space available in linux */
+ pDpa->stats.multicast = 0; /* multicast packets received */
+ pDpa->stats.collisions = RCstats.TX_totcol;
+
+ /* detailed rx_errors: */
+ pDpa->stats.rx_length_errors = 0;
+ pDpa->stats.rx_over_errors = RCstats.Rcv_orun; /* receiver ring buff overflow */
+ pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr; /* recved pkt with crc error */
+ pDpa->stats.rx_frame_errors = 0; /* recv'd frame alignment error */
+ pDpa->stats.rx_fifo_errors = 0; /* recv'r fifo overrun */
+ pDpa->stats.rx_missed_errors = 0; /* receiver missed packet */
+
+ /* detailed tx_errors */
+ pDpa->stats.tx_aborted_errors = 0;
+ pDpa->stats.tx_carrier_errors = 0;
+ pDpa->stats.tx_fifo_errors = 0;
+ pDpa->stats.tx_heartbeat_errors = 0;
+ pDpa->stats.tx_window_errors = 0;
+
+ return ((struct enet_statistics *)&(pDpa->stats));
+ }
+ return 0;
+}
+
+static int RCioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+ RCuser_struct RCuser;
+ PDPA pDpa = dev->priv;
+
+#if RCDEBUG
+ printk("RCioctl: cmd = 0x%x\n", cmd);
+#endif
+
+ switch (cmd) {
+
+ case RCU_PROTOCOL_REV:
+ /*
+ * Assign user protocol revision, to tell user-level
+ * controller program whether or not it's in sync.
+ */
+ rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;
+ break;
+
+
+ case RCU_COMMAND:
+ {
+#ifdef LINUX_2_1
+ if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
+ return -EFAULT;
+#else
+ int error;
+ error=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(RCuser));
+ if (error) {
+ return error;
+ }
+ memcpy_fromfs(&RCuser, rq->ifr_data, sizeof(RCuser));
+#endif
+
+#ifdef RCDEBUG
+ printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
+#endif
+
+ switch(RCuser.cmd)
+ {
+ case RCUC_GETFWVER:
+ printk("RC GETFWVER\n");
+ RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
+ RCGetFirmwareVer(pDpa->id, (PU8) &RCUD_GETFWVER->FirmString, NULL);
+ break;
+ case RCUC_GETINFO:
+ printk("RC GETINFO\n");
+ RCUD_GETINFO = &RCuser.RCUS_GETINFO;
+ RCUD_GETINFO -> mem_start = dev->base_addr;
+ RCUD_GETINFO -> mem_end = dev->base_addr + 2*32768;
+ RCUD_GETINFO -> base_addr = pDpa->pci_addr;
+ RCUD_GETINFO -> irq = dev->irq;
+ break;
+ case RCUC_GETIPANDMASK:
+ printk("RC GETIPANDMASK\n");
+ RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
+ RCGetRavlinIPandMask(pDpa->id, (PU32) &RCUD_GETIPANDMASK->IpAddr,
+ (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
+ break;
+ case RCUC_GETLINKSTATISTICS:
+ printk("RC GETLINKSTATISTICS\n");
+ RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS;
+ RCGetLinkStatistics(pDpa->id, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
+ break;
+ case RCUC_GETLINKSTATUS:
+ printk("RC GETLINKSTATUS\n");
+ RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
+ RCGetLinkStatus(pDpa->id, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
+ break;
+ case RCUC_GETMAC:
+ printk("RC GETMAC\n");
+ RCUD_GETMAC = &RCuser.RCUS_GETMAC;
+ RCGetMAC(pDpa->id, (PU8) &RCUD_GETMAC->mac, NULL);
+ break;
+ case RCUC_GETPROM:
+ printk("RC GETPROM\n");
+ RCUD_GETPROM = &RCuser.RCUS_GETPROM;
+ RCGetPromiscuousMode(pDpa->id, (PU32) &RCUD_GETPROM->PromMode, NULL);
+ break;
+ case RCUC_GETBROADCAST:
+ printk("RC GETBROADCAST\n");
+ RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
+ RCGetBroadcastMode(pDpa->id, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL);
+ break;
+ case RCUC_GETSPEED:
+ printk("RC GETSPEED\n");
+ if (!(dev->flags & IFF_UP))
+ {
+ printk("RCioctl, GETSPEED error: interface down\n");
+ return -ENODATA;
+ }
+ RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
+ RCGetLinkSpeed(pDpa->id, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
+ printk("RC speed = 0x%ld\n", RCUD_GETSPEED->LinkSpeedCode);
+ break;
+ case RCUC_SETIPANDMASK:
+ printk("RC SETIPANDMASK\n");
+ RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
+ printk ("RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->IpAddr >> 8) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff));
+ printk ("RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->NetMask >> 8) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff),
+ (U8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff));
+ RCSetRavlinIPandMask(pDpa->id, (U32) RCUD_SETIPANDMASK->IpAddr,
+ (U32) RCUD_SETIPANDMASK->NetMask);
+ break;
+ case RCUC_SETMAC:
+ printk("RC SETMAC\n");
+ RCUD_SETMAC = &RCuser.RCUS_SETMAC;
+ printk ("RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+ (U8) (RCUD_SETMAC->mac[0]), (U8) (RCUD_SETMAC->mac[1]), (U8) (RCUD_SETMAC->mac[2]),
+ (U8) (RCUD_SETMAC->mac[3]), (U8) (RCUD_SETMAC->mac[4]), (U8) (RCUD_SETMAC->mac[5]));
+ RCSetMAC(pDpa->id, (PU8) &RCUD_SETMAC->mac);
+ break;
+ case RCUC_SETSPEED:
+ printk("RC SETSPEED\n");
+ RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
+ RCSetLinkSpeed(pDpa->id, (U16) RCUD_SETSPEED->LinkSpeedCode);
+ printk("RC New speed = 0x%d\n", RCUD_SETSPEED->LinkSpeedCode);
+ break;
+ case RCUC_SETPROM:
+ printk("RC SETPROM\n");
+ RCUD_SETPROM = &RCuser.RCUS_SETPROM;
+ RCSetPromiscuousMode(pDpa->id,(U16)RCUD_SETPROM->PromMode);
+ printk("RC New prom mode = 0x%d\n", RCUD_SETPROM->PromMode);
+ break;
+ case RCUC_SETBROADCAST:
+ printk("RC SETBROADCAST\n");
+ RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
+ RCSetBroadcastMode(pDpa->id,(U16)RCUD_SETBROADCAST->BroadcastMode);
+ printk("RC New broadcast mode = 0x%d\n", RCUD_SETBROADCAST->BroadcastMode);
+ break;
+ default:
+ printk("RC command default\n");
+ RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
+ RCUD_DEFAULT -> rc = 0x11223344;
+ break;
+ }
+#ifdef LINUX_2_1
+ copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
+#else
+ memcpy_tofs(rq->ifr_data, &RCuser, sizeof(RCuser));
+#endif
+ break;
+ } /* RCU_COMMAND */
+
+ default:
+ printk("RC default\n");
+ rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;
+ break;
+ }
+ return 0;
+}
+
+static int RCconfig(struct device *dev, struct ifmap *map)
+{
+ /*
+ * To be completed ...
+ */
+ printk("rc: RCconfig\n");
+ return 0;
+ if (dev->flags & IFF_UP) /* can't act on a running interface */
+ return -EBUSY;
+
+ /* Don't allow changing the I/O address */
+ if (map->base_addr != dev->base_addr) {
+ printk(KERN_WARNING "RC pci45: Change I/O address not implemented\n");
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+void
+cleanup_module(void)
+{
+ PDPA pDpa;
+ struct device *next;
+
+
+#ifdef RCDEBUG
+ printk("rc: RC cleanup_module\n");
+ printk("rc: root_RCdev = 0x%x\n", (uint)root_RCdev);
+#endif
+
+
+ while (root_RCdev)
+ {
+ pDpa = (PDPA) root_RCdev->priv;
+#ifdef RCDEBUG
+ printk("rc: cleanup 0x%08X\n", (uint)root_RCdev);
+#endif
+ printk("IOP reset: 0x%x\n", RCResetIOP(pDpa->id));
+ unregister_netdev(root_RCdev);
+ next = pDpa->next;
+
+ iounmap((unsigned long *)root_RCdev->base_addr);
+ free_irq( root_RCdev->irq, root_RCdev );
+ kfree(root_RCdev);
+ root_RCdev = next;
+ }
+}
+
+static int
+RC_allocate_and_post_buffers(struct device *dev, int numBuffers)
+{
+
+ int i;
+ PDPA pDpa = (PDPA)dev->priv;
+ PU32 p;
+ psingleB pB;
+ struct sk_buff *skb;
+ RC_RETURN status;
+
+ if (!numBuffers)
+ return 0;
+ else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+ {
+#ifdef RCDEBUG
+ printk("rc: Too many buffers requested!\n");
+ printk("rc: attempting to allocate only 32 buffers\n");
+#endif
+ numBuffers = 32;
+ }
+
+ p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
+
+#ifdef RCDEBUG
+ printk("rc: TCB = 0x%x\n", (uint)p);
+#endif
+
+ if (!p)
+ {
+ printk("rc: RCopen: unable to allocate TCB\n");
+ return 0;
+ }
+
+ p[0] = 0; /* Buffer Count */
+ pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+
+#ifdef RCDEBUG
+ printk("rc: p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
+ printk("rc: pB = 0x%x\n", (uint)pB);
+#endif
+
+ for (i=0; i<numBuffers; i++)
+ {
+ skb = dev_alloc_skb(MAX_ETHER_SIZE+2);
+ if (!skb)
+ {
+ printk("rc: Doh! RCopen: unable to allocate enough skbs!\n");
+ if (*p != 0) /* did we allocate any buffers at all? */
+ {
+#ifdef RCDEBUG
+ printk("rc: will post only %d buffers \n", (uint)(*p));
+#endif
+ break;
+ }
+ else
+ {
+ kfree(p); /* Free the TCB */
+ return 0;
+ }
+ }
+#ifdef RCDEBUG
+ printk("post 0x%x\n", (uint)skb);
+#endif
+ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
+ pB->context = (U32)skb;
+ pB->scount = 1; /* segment count */
+ pB->size = MAX_ETHER_SIZE;
+ pB->addr = virt_to_bus((void *)skb->data);
+ p[0]++;
+ pB++;
+ }
+
+ if ( (status = RCPostRecvBuffers(pDpa->id, (PRCTCB)p )) != RC_RTN_NO_ERROR)
+ {
+ printk("rc: Post buffer failed with error code 0x%x!\n", status);
+ pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+ while(p[0])
+ {
+ skb = (struct sk_buff *)pB->context;
+#ifndef LINUX_2_1
+ skb->free = 1;
+#endif
+#ifdef RCDEBUG
+ printk("rc: freeing 0x%x\n", (uint)skb);
+#endif
+#ifdef LINUX_2_1
+ dev_kfree_skb (skb);
+#else
+ dev_kfree_skb(skb, FREE_READ);
+#endif
+ p[0]--;
+ pB++;
+ }
+#ifdef RCDEBUG
+ printk("rc: freed all buffers, p[0] = %ld\n", p[0]);
+#endif
+ }
+ kfree(p);
+ return(p[0]); /* return the number of posted buffers */
+}
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 8d053abf6..9b175bffa 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -39,9 +39,11 @@
#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/irq.h>
+#include <asm/uaccess.h>
#include "rrunner.h"
+
/*
* Implementation notes:
*
@@ -57,7 +59,7 @@
* stack will need to know about I/O vectors or something similar.
*/
-static const char *version = "rrunner.c: v0.06 09/02/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static const char *version = "rrunner.c: v0.09 12/14/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
static unsigned int read_eeprom(struct rr_private *rrpriv,
unsigned long offset,
@@ -68,6 +70,14 @@ static u32 read_eeprom_word(struct rr_private *rrpriv,
static int rr_load_firmware(struct device *dev);
+/*
+ * These are checked at init time to see if they are at least 256KB
+ * and increased to 256KB if they are not. This is done to avoid ending
+ * up with socket buffers smaller than the MTU size,
+ */
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
+
__initfunc(int rr_hippi_probe (struct device *dev))
{
static int i = 0;
@@ -116,6 +126,9 @@ __initfunc(int rr_hippi_probe (struct device *dev))
if (dev == NULL)
break;
+ if (!dev->priv)
+ dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL);
+
rrpriv = (struct rr_private *)dev->priv;
/* Read register base address from
@@ -194,12 +207,8 @@ __initfunc(int rr_hippi_probe (struct device *dev))
rr_init(dev);
boards_found++;
-
- /*
- * This is bollocks, but we need to tell the net-init
- * code that it shall go for the next device.
- */
dev->base_addr = 0;
+ dev = NULL;
}
/*
@@ -347,6 +356,7 @@ static int rr_reset(struct device *dev)
return 0;
}
+
/*
* Read a string from the EEPROM.
*/
@@ -356,18 +366,21 @@ static unsigned int read_eeprom(struct rr_private *rrpriv,
unsigned long length)
{
struct rr_regs *regs = rrpriv->regs;
- u32 misc, io, i;
+ u32 misc, io, host, i;
io = regs->ExtIo;
regs->ExtIo = 0;
misc = regs->LocalCtrl;
regs->LocalCtrl = 0;
+ host = regs->HostCtrl;
+ regs->HostCtrl |= HALT_NIC;
for (i = 0; i < length; i++){
regs->WinBase = (EEPROM_BASE + ((offset+i) << 3));
buf[i] = (regs->WinData >> 24) & 0xff;
}
+ regs->HostCtrl = host;
regs->LocalCtrl = misc;
regs->ExtIo = io;
@@ -391,6 +404,58 @@ static u32 read_eeprom_word(struct rr_private *rrpriv,
}
+/*
+ * Write a string to the EEPROM.
+ *
+ * This is only called when the firmware is not running.
+ */
+static unsigned int write_eeprom(struct rr_private *rrpriv,
+ unsigned long offset,
+ unsigned char *buf,
+ unsigned long length)
+{
+ struct rr_regs *regs = rrpriv->regs;
+ u32 misc, io, data, i, j, ready, error = 0;
+
+ io = regs->ExtIo;
+ regs->ExtIo = 0;
+ misc = regs->LocalCtrl;
+ regs->LocalCtrl = ENABLE_EEPROM_WRITE;
+
+ for (i = 0; i < length; i++){
+ regs->WinBase = (EEPROM_BASE + ((offset+i) << 3));
+ data = buf[i] << 24;
+ /*
+ * Only try to write the data if it is not the same
+ * value already.
+ */
+ if ((regs->WinData & 0xff000000) != data){
+ regs->WinData = data;
+ ready = 0;
+ j = 0;
+ mb();
+ while(!ready){
+ udelay(1000);
+ if ((regs->WinData & 0xff000000) == data)
+ ready = 1;
+ if (j++ > 5000){
+ printk("data mismatch: %08x, "
+ "WinData %08x\n", data,
+ regs->WinData);
+ ready = 1;
+ error = 1;
+ }
+ }
+ }
+ }
+
+ regs->LocalCtrl = misc;
+ regs->ExtIo = io;
+
+ return error;
+}
+
+
__initfunc(static int rr_init(struct device *dev))
{
struct rr_private *rrpriv;
@@ -404,8 +469,13 @@ __initfunc(static int rr_init(struct device *dev))
if (rev > 0x00020024)
printk(" Firmware revision: %i.%i.%i\n", (rev >> 16),
((rev >> 8) & 0xff), (rev & 0xff));
- else{
- printk(" Firmware revision too old: %i.%i.%i, please upgrade to 2.0.37 or later.\n",
+ else if (rev >= 0x00020000) {
+ printk(" Firmware revision: %i.%i.%i (2.0.37 or "
+ "later is recommended)\n", (rev >> 16),
+ ((rev >> 8) & 0xff), (rev & 0xff));
+ }else{
+ printk(" Firmware revision too old: %i.%i.%i, please "
+ "upgrade to 2.0.37 or later.\n",
(rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff));
return -EFAULT;
@@ -416,6 +486,18 @@ __initfunc(static int rr_init(struct device *dev))
sram_size = read_eeprom_word(rrpriv, (void *)8);
printk(" SRAM size 0x%06x\n", sram_size);
+ if (sysctl_rmem_max < 262144){
+ printk(" Receive socket buffer limit too low (%i), "
+ "setting to 262144\n", sysctl_rmem_max);
+ sysctl_rmem_max = 262144;
+ }
+
+ if (sysctl_wmem_max < 262144){
+ printk(" Transmit socket buffer limit too low (%i), "
+ "setting to 262144\n", sysctl_wmem_max);
+ sysctl_wmem_max = 262144;
+ }
+
return 0;
}
@@ -574,7 +656,9 @@ static int rr_init1(struct device *dev)
}
#endif
dev->tbusy = 0;
+#if 0
dev->interrupt = 0;
+#endif
dev->start = 1;
return 0;
}
@@ -590,9 +674,6 @@ static u32 rr_handle_event(struct device *dev, u32 prodidx)
struct rr_private *rrpriv;
struct rr_regs *regs;
u32 tmp, eidx;
-#if 0
- short i;
-#endif
rrpriv = (struct rr_private *)dev->priv;
regs = rrpriv->regs;
@@ -710,7 +791,8 @@ static int rx_int(struct device *dev, u32 rxlimit)
if (pkt_len < PKT_COPY_THRESHOLD) {
skb = alloc_skb(pkt_len, GFP_ATOMIC);
if (skb == NULL){
- printk("%s: Out of memory deferring packet\n", dev->name);
+ printk("%s: Out of memory deferring "
+ "packet\n", dev->name);
rrpriv->stats.rx_dropped++;
goto defer;
}else
@@ -720,14 +802,16 @@ static int rx_int(struct device *dev, u32 rxlimit)
}else{
struct sk_buff *newskb;
- newskb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC);
+ newskb = alloc_skb(dev->mtu + HIPPI_HLEN,
+ GFP_ATOMIC);
if (newskb){
skb = rrpriv->rx_skbuff[index];
skb_put(skb, pkt_len);
rrpriv->rx_skbuff[index] = newskb;
rrpriv->rx_ring[index].addr = virt_to_bus(newskb->data);
}else{
- printk("%s: Out of memory, deferring packet\n", dev->name);
+ printk("%s: Out of memory, deferring "
+ "packet\n", dev->name);
rrpriv->stats.rx_dropped++;
goto defer;
}
@@ -766,18 +850,15 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
rrpriv = (struct rr_private *)dev->priv;
regs = rrpriv->regs;
- if (!(regs->HostCtrl & RR_INT)){
-#if 0
- /* These are harmless */
- printk("%s: spurious interrupt detected\n", dev->name);
-#endif
+ if (!(regs->HostCtrl & RR_INT))
return;
- }
+#if 0
if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) {
printk("%s: Re-entering the interrupt handler.\n", dev->name);
return;
}
+#endif
spin_lock_irqsave(&rrpriv->lock, flags);
@@ -828,7 +909,9 @@ static void rr_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
spin_unlock_irqrestore(&rrpriv->lock, flags);
+#if 0
dev->interrupt = 0;
+#endif
}
@@ -844,7 +927,7 @@ static int rr_open(struct device *dev)
regs->HostCtrl |= (HALT_NIC | RR_CLEAR_INT);
#endif
- if (request_irq(dev->irq, rr_interrupt, 0, rrpriv->name, dev))
+ if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev))
{
printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
dev->name, dev->irq);
@@ -858,7 +941,9 @@ static int rr_open(struct device *dev)
rr_init1(dev);
dev->tbusy = 0;
+#if 0
dev->interrupt = 0;
+#endif
dev->start = 1;
MOD_INC_USE_COUNT;
@@ -942,6 +1027,12 @@ static int rr_close(struct device *dev)
rrpriv = (struct rr_private *)dev->priv;
regs = rrpriv->regs;
+ /*
+ * Lock to make sure we are not cleaning up while another CPU
+ * handling interrupts.
+ */
+ spin_lock(&rrpriv->lock);
+
tmp = regs->HostCtrl;
if (tmp & NIC_HALTED){
printk("%s: NIC already halted\n", dev->name);
@@ -950,11 +1041,7 @@ static int rr_close(struct device *dev)
tmp |= HALT_NIC;
regs->HostCtrl = tmp;
- /*
- * Lock to make sure we are not cleaning up while another CPU
- * handling interrupts.
- */
- spin_lock(&rrpriv->lock);
+ rrpriv->fw_running = 0;
regs->TxPi = 0;
regs->IpRxPi = 0;
@@ -1080,9 +1167,6 @@ static int rr_load_firmware(struct device *dev)
{
struct rr_private *rrpriv;
struct rr_regs *regs;
-#if 0
- unsigned long flags;
-#endif
int i, j;
u32 localctrl, eptr, sptr, segptr, len, tmp;
u32 p2len, p2size, nr_seg, revision, io, sram_size;
@@ -1179,30 +1263,117 @@ out:
static int rr_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
struct rr_private *rrpriv;
+ unsigned char *image, *oldimage;
+ unsigned int i;
+ int error = -EOPNOTSUPP;
rrpriv = (struct rr_private *)dev->priv;
+ spin_lock(&rrpriv->lock);
+
switch(cmd){
+ case SIOCRRGFW:
+ if (!suser()){
+ error = -EPERM;
+ goto out;
+ }
+
+ if (rrpriv->fw_running){
+ printk("%s: Firmware already running\n", dev->name);
+ error = -EPERM;
+ goto out;
+ }
+
+ image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+ if (!image){
+ printk(KERN_ERR "%s: Unable to allocate memory "
+ "for EEPROM image\n", dev->name);
+ error = -ENOMEM;
+ goto out;
+ }
+ i = read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
+ if (i != EEPROM_BYTES){
+ kfree(image);
+ printk(KERN_ERR "%s: Error reading EEPROM\n",
+ dev->name);
+ error = -EFAULT;
+ goto out;
+ }
+ error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
+ if (error)
+ error = -EFAULT;
+ kfree(image);
+ break;
case SIOCRRPFW:
- if (!suser())
- return -EPERM;
+ if (!suser()){
+ error = -EPERM;
+ goto out;
+ }
if (rrpriv->fw_running){
- printk("%s: firmware already running\n", dev->name);
- return -EPERM;
+ printk("%s: Firmware already running\n", dev->name);
+ error = -EPERM;
+ goto out;
}
- printk("%s: updating firmware", dev->name);
+
+ image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+ if (!image){
+ printk(KERN_ERR "%s: Unable to allocate memory "
+ "for EEPROM image\n", dev->name);
+ error = -ENOMEM;
+ goto out;
+ }
+
+ oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+ if (!image){
+ printk(KERN_ERR "%s: Unable to allocate memory "
+ "for old EEPROM image\n", dev->name);
+ error = -ENOMEM;
+ goto out;
+ }
+
+ error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
+ if (error)
+ error = -EFAULT;
+
+ printk("%s: Updating EEPROM firmware\n", dev->name);
+
+ error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
+ if (error)
+ printk(KERN_ERR "%s: Error writing EEPROM\n",
+ dev->name);
+
+ i = read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);
+ if (i != EEPROM_BYTES)
+ printk(KERN_ERR "%s: Error reading back EEPROM "
+ "image\n", dev->name);
+
+ error = memcmp(image, oldimage, EEPROM_BYTES);
+ if (error){
+ printk(KERN_ERR "%s: Error verifying EEPROM image\n",
+ dev->name);
+ error = -EFAULT;
+ }
+
+ kfree(image);
+ kfree(oldimage);
+ break;
+ case SIOCRRID:
+ error = put_user(0x52523032, (int *)(&rq->ifr_data[0]));
+ if (error)
+ error = -EFAULT;
break;
default:
- return -EOPNOTSUPP;
}
- return 0;
+ out:
+ spin_unlock(&rrpriv->lock);
+ return error;
}
/*
* Local variables:
- * compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c"
+ * compile-command: "gcc -D__SMP__ -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c"
* End:
*/
diff --git a/drivers/net/rrunner.h b/drivers/net/rrunner.h
index f6e6b3c31..d47513700 100644
--- a/drivers/net/rrunner.h
+++ b/drivers/net/rrunner.h
@@ -550,6 +550,7 @@ struct rx_desc{
#define SIOCRRPFW SIOCDEVPRIVATE /* put firmware */
#define SIOCRRGFW SIOCDEVPRIVATE+1 /* get firmware */
+#define SIOCRRID SIOCDEVPRIVATE+2 /* identify */
struct seg_hdr {
@@ -560,6 +561,8 @@ struct seg_hdr {
#define EEPROM_BASE 0x80000000
+#define EEPROM_WORDS 8192
+#define EEPROM_BYTES (EEPROM_WORDS * sizeof(u32))
struct eeprom_boot {
u32 key1;
diff --git a/drivers/net/sdla.c b/drivers/net/sdla.c
index c8740a8d1..32f22e14d 100644
--- a/drivers/net/sdla.c
+++ b/drivers/net/sdla.c
@@ -248,7 +248,7 @@ int sdla_z80_poll(struct device *dev, int z80_addr, int jiffs, char resp1, char
temp += z80_addr & SDLA_ADDR_MASK;
resp = ~resp1;
- while ((jiffies < done) && (resp != resp1) && (!resp2 || (resp != resp2)))
+ while (time_before(jiffies, done) && (resp != resp1) && (!resp2 || (resp != resp2)))
{
if (jiffies != now)
{
@@ -257,7 +257,7 @@ int sdla_z80_poll(struct device *dev, int z80_addr, int jiffs, char resp1, char
resp = *temp;
}
}
- return(jiffies < done ? jiffies - start : -1);
+ return(time_before(jiffies, done) ? jiffies - start : -1);
}
/* constants for Z80 CPU speed */
@@ -444,7 +444,7 @@ static int sdla_cmd(struct device *dev, int cmd, short dlci, short flags,
waiting = 1;
len = 0;
- while (waiting && (jiffies <= jiffs))
+ while (waiting && time_before_eq(jiffies, jiffs))
{
if (waiting++ % 3)
{
diff --git a/drivers/net/sdla_fr.c b/drivers/net/sdla_fr.c
index 0a886c6db..ecf784758 100644
--- a/drivers/net/sdla_fr.c
+++ b/drivers/net/sdla_fr.c
@@ -1078,6 +1078,8 @@ static int if_send(struct sk_buff *skb, struct device *dev)
++chan->if_send_bfrs_passed_to_adptr;
++chan->ifstats.tx_packets;
++card->wandev.stats.tx_packets;
+ chan->ifstats.tx_bytes += skb->len;
+ card->wandev.stats.tx_bytes += skb->len;
}
}
}
@@ -1501,6 +1503,8 @@ static void fr502_rx_intr(sdla_t * card)
netif_rx(skb);
++chan->ifstats.rx_packets;
++card->wandev.stats.rx_packets;
+ chan->ifstats.rx_bytes += skb->len;
+ card->wandev.stats.rx_bytes += skb->len;
}
}
sdla_mapmem(&card->hw, FR_MB_VECTOR);
@@ -1621,6 +1625,8 @@ static void fr508_rx_intr(sdla_t * card)
++chan->rx_intr_bfr_passed_to_stack;
++chan->ifstats.rx_packets;
++card->wandev.stats.rx_packets;
+ chan->ifstats.rx_bytes += skb->len;
+ card->wandev.stats.rx_bytes += skb->len;
}
}
}
diff --git a/drivers/net/sdla_ppp.c b/drivers/net/sdla_ppp.c
index 69038be9a..ec9b71b85 100644
--- a/drivers/net/sdla_ppp.c
+++ b/drivers/net/sdla_ppp.c
@@ -698,6 +698,7 @@ static int if_send(struct sk_buff *skb, struct device *dev)
} else {
++ppp_priv_area->if_send_bfr_passed_to_adptr;
++card->wandev.stats.tx_packets;
+ card->wandev.stats.tx_bytes += skb->len;
}
}
tx_done:
@@ -1202,6 +1203,7 @@ static void rx_intr(sdla_t * card)
skb->mac.raw = skb->data;
netif_rx(skb);
++card->wandev.stats.rx_packets;
+ card->wandev.stats.rx_bytes += skb->len;
++ppp_priv_area->rx_intr_bfr_passed_to_stack;
}
} else {
diff --git a/drivers/net/sdla_x25.c b/drivers/net/sdla_x25.c
index 5aa649117..0ef2771d8 100644
--- a/drivers/net/sdla_x25.c
+++ b/drivers/net/sdla_x25.c
@@ -38,9 +38,6 @@
* Jan 07, 1997 Gene Kozin Initial version.
*****************************************************************************/
-#if !defined(__KERNEL__) || !defined(MODULE)
-#error This code MUST be compiled as a kernel module!
-#endif
#include <linux/kernel.h> /* printk(), and other useful stuff */
#include <linux/stddef.h> /* offsetof(), etc. */
@@ -1031,6 +1028,7 @@ static void rx_intr (sdla_t* card)
{
netif_rx(skb);
++chan->ifstats.rx_packets;
+ chan->ifstats.rx_bytes += skb->len;
}
}
}
@@ -2125,6 +2123,7 @@ static int chan_send (struct device* dev, struct sk_buff* skb)
return 1;
}
++chan->ifstats.tx_packets;
+ chan->ifstats.tx_bytes += skb->len;
break;
case 0x33: /* Tx busy */
diff --git a/drivers/net/sdladrv.c b/drivers/net/sdladrv.c
index 46992d97a..1ddf31a98 100644
--- a/drivers/net/sdladrv.c
+++ b/drivers/net/sdladrv.c
@@ -493,7 +493,7 @@ int sdla_down (sdlahw_t* hw)
}
/*============================================================================
- * Map shared memory window into SDLA adress space.
+ * Map shared memory window into SDLA address space.
*/
EXPORT_SYMBOL(sdla_mapmem);
diff --git a/drivers/net/sdlamain.c b/drivers/net/sdlamain.c
index 00454c5d6..3c7eef8c2 100644
--- a/drivers/net/sdlamain.c
+++ b/drivers/net/sdlamain.c
@@ -29,10 +29,6 @@
* Jan 02, 1997 Gene Kozin Initial version.
*****************************************************************************/
-#if !defined(__KERNEL__) || !defined(MODULE)
-#error This code MUST be compiled as a kernel module!
-#endif
-
#include <linux/config.h> /* OS configuration options */
#include <linux/stddef.h> /* offsetof(), etc. */
#include <linux/errno.h> /* return codes */
@@ -122,7 +118,12 @@ static struct tq_struct sdla_tq =
* < 0 error.
* Context: process
*/
+
+#ifdef MODULE
int init_module (void)
+#else
+int wanpipe_init(void)
+#endif
{
int cnt, err = 0;
@@ -173,6 +174,7 @@ int init_module (void)
return err;
}
+#ifdef MODULE
/*============================================================================
* Module 'remove' entry point.
* o unregister all adapters from the WAN router
@@ -190,6 +192,8 @@ void cleanup_module (void)
kfree(card_array);
}
+#endif
+
/******* WAN Device Driver Entry Points *************************************/
/*============================================================================
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index b571dc28c..c01c31d5b 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -247,10 +247,10 @@ __initfunc(static int seeq8005_probe1(struct device *dev, int ioaddr))
outw(0x5a5a, SEEQ_BUFFER);
}
j=jiffies+HZ;
- while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && jiffies < j )
+ while ( ((inw(SEEQ_STATUS) & SEEQSTAT_FIFO_EMPTY) != SEEQSTAT_FIFO_EMPTY) && time_before(jiffies, j) )
mb();
outw( 0 , SEEQ_DMAAR);
- while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < j+HZ)
+ while ( ((inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, j+HZ))
mb();
if ( (inw(SEEQ_STATUS) & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
outw( SEEQCMD_WINDOW_INT_ACK | (inw(SEEQ_STATUS)& SEEQCMD_INT_MASK), SEEQ_CMD);
@@ -707,7 +707,7 @@ static void hardware_send_packet(struct device * dev, char *buf, int length)
/* drain FIFO */
tmp = jiffies;
- while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies < tmp + HZ))
+ while ( (((status=inw(SEEQ_STATUS)) & SEEQSTAT_FIFO_EMPTY) == 0) && (jiffies - tmp < HZ))
mb();
/* doit ! */
@@ -729,7 +729,7 @@ inline void wait_for_buffer(struct device * dev)
int status;
tmp = jiffies + HZ;
- while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && jiffies < tmp)
+ while ( ( ((status=inw(SEEQ_STATUS)) & SEEQSTAT_WINDOW_INT) != SEEQSTAT_WINDOW_INT) && time_before(jiffies, tmp))
mb();
if ( (status & SEEQSTAT_WINDOW_INT) == SEEQSTAT_WINDOW_INT)
diff --git a/drivers/net/sktr.c b/drivers/net/sktr.c
index f86acd1fb..7bc4f256f 100644
--- a/drivers/net/sktr.c
+++ b/drivers/net/sktr.c
@@ -1020,7 +1020,7 @@ static void sktr_timer_chk(unsigned long data)
return;
sktr_chk_outstanding_cmds(dev);
- if(tp->LastSendTime + SEND_TIMEOUT < jiffies
+ if(time_before(tp->LastSendTime + SEND_TIMEOUT, jiffies)
&& (tp->QueueSkb < MAX_TX_QUEUE || tp->TplFree != tp->TplBusy))
{
/* Anything to send, but stalled to long */
@@ -1068,7 +1068,7 @@ static void sktr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if(!sktr_chk_ssb(tp, irq_type))
{
- printk(KERN_INFO "%s: DATA LATE occured\n", dev->name);
+ printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
break;
}
@@ -1526,11 +1526,11 @@ static void sktr_wait(unsigned long time)
{
long tmp;
- tmp = time/(1000000/HZ);
+ tmp = jiffies + time/(1000000/HZ);
do {
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
tmp = schedule_timeout(tmp);
- } while(tmp);
+ } while(time_after(tmp, jiffies));
return;
}
@@ -1583,7 +1583,7 @@ static int sktr_reset_adapter(struct device *dev)
c |= ACL_SPEED16; /* Set 16Mbps */
}
- /* In case a comand is pending - forget it */
+ /* In case a command is pending - forget it */
tp->ScbInUse = 0;
c &= ~ACL_ARESET; /* Clear adapter reset bit */
@@ -1672,7 +1672,7 @@ static int sktr_bringup_diags(struct device *dev)
} while(retry_cnt > 0);
Status = inw(ioaddr + SIFSTS);
- Status &= STS_ERROR_MASK; /* Hardware error occured! */
+ Status &= STS_ERROR_MASK; /* Hardware error occurred! */
printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
dev->name, Status);
@@ -1761,7 +1761,7 @@ static int sktr_init_adapter(struct device *dev)
{
if((Status & STS_ERROR) != 0)
{
- /* Initialization error occured */
+ /* Initialization error occurred */
Status = inw(ioaddr + SIFSTS);
Status &= STS_ERROR_MASK;
/* ShowInitialisationErrorCode(Status); */
diff --git a/drivers/net/sktr_firmware.h b/drivers/net/sktr_firmware.h
index bef17faa4..25dd973d4 100644
--- a/drivers/net/sktr_firmware.h
+++ b/drivers/net/sktr_firmware.h
@@ -1,6 +1,6 @@
/*
* The firmware this driver downloads into the tokenring card is a
- * seperate program and is not GPL'd source code, even though the Linux
+ * separate program and is not GPL'd source code, even though the Linux
* side driver and the routine that loads this data into the card are.
*
* This firmware is licensed to you strictly for use in conjunction
diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
index 13a020869..118a0e1ec 100644
--- a/drivers/net/slhc.c
+++ b/drivers/net/slhc.c
@@ -51,14 +51,16 @@
*/
#include <linux/config.h>
-#ifdef CONFIG_INET
-/* Entire module is for IP only */
#include <linux/module.h>
-
#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+
+#ifdef CONFIG_INET
+/* Entire module is for IP only */
#include <linux/sched.h>
#include <linux/mm.h>
-#include <linux/string.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/termios.h>
@@ -72,7 +74,6 @@
#include <net/tcp.h>
#include <linux/skbuff.h>
#include <net/sock.h>
-#include <linux/errno.h>
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -758,4 +759,52 @@ __initfunc(void slhc_install(void))
}
#endif /* MODULE */
+#else /* CONFIG_INET */
+EXPORT_SYMBOL(slhc_init);
+EXPORT_SYMBOL(slhc_free);
+EXPORT_SYMBOL(slhc_remember);
+EXPORT_SYMBOL(slhc_compress);
+EXPORT_SYMBOL(slhc_uncompress);
+EXPORT_SYMBOL(slhc_toss);
+
+int
+slhc_toss(struct slcompress *comp)
+{
+ printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
+ return -EINVAL;
+}
+int
+slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
+{
+ printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
+ return -EINVAL;
+}
+int
+slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
+ unsigned char *ocp, unsigned char **cpp, int compress_cid)
+{
+ printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
+ return -EINVAL;
+}
+
+int
+slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
+{
+ printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
+ return -EINVAL;
+}
+
+void
+slhc_free(struct slcompress *comp)
+{
+ printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
+ return;
+}
+struct slcompress *
+slhc_init(int rslots, int tslots)
+{
+ printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
+ return NULL;
+}
+
#endif /* CONFIG_INET */
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index cd10798a2..a588a1b9a 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -375,7 +375,6 @@ void cleanup_module(void)
/* NB: ultra_close_card() does free_irq */
int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
release_region(ioaddr, ULTRA_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index f51ced5ad..dbb30af09 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -483,7 +483,6 @@ cleanup_module(void)
void *priv = dev->priv;
/* NB: ultra_close_card() does free_irq */
release_region(ioaddr, ULTRA_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index 64772c48c..f78f02a6e 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -413,7 +413,6 @@ void cleanup_module(void)
void *priv = dev->priv;
/* NB: ultra32_close_card() does free_irq */
release_region(ioaddr, ULTRA32_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
}
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index e93207339..d3d2fba46 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -2797,7 +2797,7 @@ void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
*
* Returns:
* No error = 0, else, the stage at which the error
- * occured.
+ * occurred.
* Parms:
* io_base The IO port base address for the
* TLAN device with the EEPROM to
diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c
index 04ddcef20..555776826 100644
--- a/drivers/net/tulip.c
+++ b/drivers/net/tulip.c
@@ -1,13 +1,13 @@
-/* tulip.c: A DEC 21040-family ethernet driver for linux. */
+/* tulip.c: A DEC 21040-family ethernet driver for Linux. */
/*
- NOTICE: THIS IS THE ALPHA TEST VERSION!
- Written 1994-1997 by Donald Becker.
+ Written 1994-1998 by Donald Becker.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
- This driver is for the SMC EtherPower PCI ethernet adapter.
- It should work with most other DEC 21*40-based ethercards.
+ This driver is for the Digital "Tulip" ethernet adapter interface.
+ It should work with most DEC 21*4*-based chips/ethercards, as well as
+ PNIC and MXIC chips.
The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
Center of Excellence in Space Data and Information Sciences
@@ -17,14 +17,27 @@
http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
*/
-static const char *version = "tulip.c:v0.83 10/19/97 becker@cesdis.gsfc.nasa.gov\n";
+#define SMP_CHECK
+static const char version[] = "tulip.c:v0.89H 5/23/98 becker@cesdis.gsfc.nasa.gov\n";
/* A few user-configurable values. */
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 25;
+
+#define MAX_UNITS 8
/* Used to pass the full-duplex flag, etc. */
-static int full_duplex[8] = {0, };
-static int options[8] = {0, };
-static int mtu[8] = {0, }; /* Jumbo MTU for interfaces. */
+static int full_duplex[MAX_UNITS] = {0, };
+static int options[MAX_UNITS] = {0, };
+static int mtu[MAX_UNITS] = {0, }; /* Jumbo MTU for interfaces. */
+
+/* The possible media types that can be set in options[] are: */
+static const char * const medianame[] = {
+ "10baseT", "10base2", "AUI", "100baseTx",
+ "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx",
+ "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII",
+ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
+};
/* Set if the PCI BIOS detects the chips on a multiport board backwards. */
#ifdef REVERSE_PROBE_ORDER
@@ -38,40 +51,20 @@ static int reverse_probe = 0;
bonding and packet priority.
There are no ill effects from too-large receive rings. */
#define TX_RING_SIZE 16
-#define RX_RING_SIZE 16
+#define RX_RING_SIZE 32
/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
#ifdef __alpha__
-static const int rx_copybreak = 1518;
+static int rx_copybreak = 1518;
#else
-static const int rx_copybreak = 100;
+static int rx_copybreak = 100;
#endif
-/* The following example shows how to always use the 10base2 port. */
-#ifdef notdef
-#define TULIP_DEFAULT_MEDIA 1 /* 1 == 10base2 */
-#define TULIP_NO_MEDIA_SWITCH /* Don't switch from this port */
-#endif
-
-/* Define to force full-duplex operation on all Tulip interfaces. */
-/* #define TULIP_FULL_DUPLEX 1 */
-
/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT ((2000*HZ)/1000)
+#define TX_TIMEOUT (4*HZ)
-#include <linux/config.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -82,6 +75,7 @@ static const int rx_copybreak = 100;
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
@@ -106,28 +100,10 @@ static const int rx_copybreak = 100;
#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
#endif
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
-#ifdef MODULE
-#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
-char kernel_version[] = UTS_RELEASE;
-#endif
-#else
-#undef MOD_INC_USE_COUNT
-#define MOD_INC_USE_COUNT
-#undef MOD_DEC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-#endif /* 1.3.38 */
-
#if (LINUX_VERSION_CODE >= 0x10344)
#define NEW_MULTICAST
#include <linux/delay.h>
#endif
-#if (LINUX_VERSION_CODE >= 0x20100)
-#ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
-#endif
-#endif
#ifdef SA_SHIRQ
#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
#else
@@ -135,8 +111,8 @@ char kernel_version[] = UTS_RELEASE;
#endif
#if (LINUX_VERSION_CODE < 0x20123)
+#define hard_smp_processor_id() smp_processor_id()
#define test_and_set_bit(val, addr) set_bit(val, addr)
-#include <linux/bios32.h>
#endif
/* This my implementation of shared IRQs, now only used for 1.2.13. */
@@ -167,7 +143,7 @@ I. Board Compatibility
This device driver is designed for the DECchip "Tulip", Digital's
single-chip ethernet controllers for PCI. Supported members of the family
-are the 21040, 21041, 21140, 21140A and 21142. These chips are used on
+are the 21040, 21041, 21140, 21140A, 21142, and 21143. These chips are used on
many PCI boards including the SMC EtherPower series.
@@ -268,44 +244,65 @@ register of the set CSR12-15 written. Hmmm, now how is that possible? */
#ifndef PCI_VENDOR_ID_LITEON
#define PCI_VENDOR_ID_LITEON 0x11AD
-#define PCI_DEVICE_ID_PNIC 0x0002
-#define PCI_DEVICE_ID_PNIC_X 0x0168
-#else
-/* Now PCI_VENDOR_ID_LITEON is defined, but device IDs have different names */
-#define PCI_DEVICE_ID_PNIC PCI_DEVICE_ID_LITEON_LNE100TX
-#define PCI_DEVICE_ID_PNIC_X 0x0168
+#endif
+
+#ifndef PCI_VENDOR_ID_MXIC
+#define PCI_VENDOR_ID_MXIC 0x10d9
+#define PCI_DEVICE_ID_MX98713 0x0512
+#define PCI_DEVICE_ID_MX98715 0x0531
+#define PCI_DEVICE_ID_MX98725 0x0531
#endif
/* The rest of these values should never change. */
static void tulip_timer(unsigned long data);
+static void t21142_timer(unsigned long data);
+static void mxic_timer(unsigned long data);
+static void pnic_timer(unsigned long data);
/* A table describing the chip types. */
+enum tbl_flag { HAS_MII=1, HAS_MEDIA_TABLE = 2, CSR12_IN_SROM = 4,};
static struct tulip_chip_table {
- int device_id;
- char *chip_name;
- int flags;
- void (*media_timer)(unsigned long data);
+ int vendor_id, device_id;
+ char *chip_name;
+ int io_size;
+ int valid_intrs; /* CSR7 interrupt enable settings */
+ int flags;
+ void (*media_timer)(unsigned long data);
} tulip_tbl[] = {
- { PCI_DEVICE_ID_DEC_TULIP, "Digital DS21040 Tulip", 0, tulip_timer },
- { PCI_DEVICE_ID_DEC_TULIP_PLUS, "Digital DS21041 Tulip", 0, tulip_timer },
- { PCI_DEVICE_ID_DEC_TULIP_FAST, "Digital DS21140 Tulip", 0, tulip_timer },
- { PCI_DEVICE_ID_DEC_TULIP_21142, "Digital DS21142/3 Tulip", 0, tulip_timer },
- { PCI_DEVICE_ID_PNIC_X, "Lite-On 82c168 PNIC", 0, tulip_timer },
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
+ "Digital DC21040 Tulip", 128, 0x0001ebef, 0, tulip_timer },
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
+ "Digital DC21041 Tulip", 128, 0x0001ebef, HAS_MEDIA_TABLE, tulip_timer },
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
+ "Digital DS21140 Tulip", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM,
+ tulip_timer },
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_21142,
+ "Digital DS21142/3 Tulip", 128, 0x0801fbff,
+ HAS_MII | HAS_MEDIA_TABLE, t21142_timer },
+ { PCI_VENDOR_ID_LITEON, 0x0002,
+ "Lite-On 82c168 PNIC", 256, 0x0001ebef, HAS_MII, pnic_timer },
+ { PCI_VENDOR_ID_MXIC, PCI_DEVICE_ID_MX98713,
+ "Macronix 98713 PMAC", 128, 0x0001ebef,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer /* Tulip-like! */ },
+ { PCI_VENDOR_ID_MXIC, PCI_DEVICE_ID_MX98715,
+ "Macronix 98715 PMAC", 256, 0x0001ebef, HAS_MEDIA_TABLE, mxic_timer },
+ { PCI_VENDOR_ID_MXIC, PCI_DEVICE_ID_MX98725,
+ "Macronix 98725 PMAC", 256, 0x0001ebef, HAS_MEDIA_TABLE, mxic_timer },
+ { 0x125B, 0x1400, "ASIX AX88140", 128, 0x0001fbff,
+ HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer },
{0, 0, 0, 0},
};
/* This matches the table above. */
-enum chips { DC21040=0, DC21041=1, DC21140=2, DC21142=3, LC82C168};
-
-static const char * const medianame[] = {
- "10baseT", "10base2", "AUI", "100baseTx",
- "10baseT-FD", "100baseTx-FD", "100baseT4", "100baseFx",
- "100baseFx-FD", "MII 10baseT", "MII 10baseT-FD", "MII",
- "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4",
-};
-/* A full-duplex map for above. */
-static const char media_fd[] =
-{0,0,0,0, 0xff,0xff,0,0, 0xff,0,0xff,0x01, 0,0,0xff,0 };
+enum chips { DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3,
+ LC82C168, MX98713, MX98715, MX98725};
+
+/* A full-duplex map for media types. */
+enum MediaIs {MediaIsFD = 1, MediaAlwaysFD=2, MediaIsMII=4, MediaIsFx=8,
+ MediaIs100=16};
+static const char media_cap[] =
+{0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20 };
/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
static u16 t21041_csr13[] = { 0xEF05, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
@@ -325,9 +322,9 @@ enum tulip_offsets {
/* The bits in the CSR5 status registers, mostly interrupt sources. */
enum status_bits {
TimerInt=0x800, TPLnkFail=0x1000, TPLnkPass=0x10,
+ NormalIntr=0x10000, AbnormalIntr=0x8000,
RxJabber=0x200, RxDied=0x100, RxNoBuf=0x80, RxIntr=0x40,
- TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02,
- TxIntr=0x01,
+ TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
};
/* The Tulip Rx and Tx buffer descriptors. */
@@ -352,7 +349,7 @@ struct medialeaf {
struct mediatable {
u16 defaultmedia;
u8 leafcount, csr12dir; /* General purpose pin directions. */
- unsigned has_mii:1;
+ unsigned has_mii:1, has_nonmii:1;
struct medialeaf mleaf[0];
};
@@ -360,7 +357,6 @@ struct mediainfo {
struct mediainfo *next;
int info_type;
int index;
- struct non_mii { char media; unsigned char csr12val; char bitnum, flags;} non_mii;
unsigned char *info;
};
@@ -384,32 +380,38 @@ struct tulip_private {
struct enet_statistics stats;
#endif
struct timer_list timer; /* Media selection timer. */
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- int fc_bit;
+ int interrupt; /* In-interrupt flag. */
+#ifdef SMP_CHECK
+ int smp_proc_id; /* Which processor in IRQ handler. */
#endif
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
unsigned int tx_full:1; /* The Tx queue is full. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int full_duplex_lock:1;
+ unsigned int fake_addr:1; /* Multiport board faked address. */
unsigned int default_port:4; /* Last dev->if_port value. */
unsigned int media2:4; /* Secondary monitored media port. */
unsigned int medialock:1; /* Don't sense media type. */
unsigned int mediasense:1; /* Media sensing in progress. */
unsigned int csr6; /* Current CSR6 control settings. */
unsigned char eeprom[128]; /* Serial EEPROM contents. */
- signed char phys[4]; /* MII device addresses. */
+ u16 to_advertise; /* NWay capabilities advertised. */
+ u16 advertising[4];
+ signed char phys[4], mii_cnt; /* MII device addresses. */
struct mediatable *mtable;
int cur_index; /* Current media index. */
- unsigned char pci_bus, pci_device_fn;
+ unsigned char pci_bus, pci_dev_fn;
int pad0, pad1; /* Used for 8-byte alignment */
};
-static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
+static struct device *tulip_probe1(int pci_bus, int pci_devfn,
+ struct device *dev,
int chip_id, int options);
static void parse_eeprom(struct device *dev);
-static int read_eeprom(int ioaddr, int location);
-static int mdio_read(int ioaddr, int phy_id, int location);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(struct device *dev, int phy_id, int location);
+static void mdio_write(struct device *dev, int phy_id, int location, int value);
static void select_media(struct device *dev, int startup);
static int tulip_open(struct device *dev);
static void tulip_timer(unsigned long data);
@@ -420,24 +422,19 @@ static int tulip_rx(struct device *dev);
static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs);
static int tulip_close(struct device *dev);
static struct enet_statistics *tulip_get_stats(struct device *dev);
+#ifdef HAVE_PRIVATE_IOCTL
+static int private_ioctl(struct device *dev, struct ifreq *rq, int cmd);
+#endif
#ifdef NEW_MULTICAST
-static void set_multicast_list(struct device *dev);
+static void set_rx_mode(struct device *dev);
#else
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
-#ifdef CONFIG_NET_FASTROUTE
-#include <linux/if_arp.h>
-#include <net/ip.h>
-
-static int tulip_accept_fastpath(struct device *dev, struct dst_entry *dst);
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
#endif
-#ifdef MODULE
/* A list of all installed Tulip devices, for removing the driver module. */
static struct device *root_tulip_dev = NULL;
-#endif
/* This 21040 probe no longer uses a large fixed contiguous Rx buffer region,
but now receives directly into full-sized skbuffs that are allocated
@@ -449,121 +446,118 @@ int tulip_probe(struct device *dev)
{
int cards_found = 0;
static int pci_index = 0; /* Static, for multiple probe calls. */
+ unsigned char pci_bus, pci_device_fn;
/* Ideally we would detect all network cards in slot order. That would
be best done a central PCI probe dispatch, which wouldn't work
well with the current structure. So instead we detect just the
Tulip cards in slot order. */
- if (pci_present()) {
- unsigned char pci_bus, pci_device_fn;
-
- for (;pci_index < 0xff; pci_index++) {
- unsigned char pci_latency;
#if LINUX_VERSION_CODE >= 0x20155
- unsigned int pci_irq_line;
- struct pci_dev *pdev;
+ if (! pci_present())
+ return -ENODEV;
#else
- unsigned char pci_irq_line;
-#endif
- unsigned short pci_command, vendor, device;
- unsigned int pci_ioaddr, chip_idx = 0;
-
- if (pcibios_find_class
- (PCI_CLASS_NETWORK_ETHERNET << 8,
- reverse_probe ? 0xfe - pci_index : pci_index,
- &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) {
- if (reverse_probe)
- continue;
- else
- break;
- }
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_VENDOR_ID, &vendor);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_DEVICE_ID, &device);
+ if (! pcibios_present())
+ return -ENODEV;
+#endif
+ for (;pci_index < 0xff; pci_index++) {
+ u16 vendor, device, pci_command, new_command;
+ unsigned long pci_ioaddr = 0;
+ int chip_idx = 0;
+
+ if (pcibios_find_class
+ (PCI_CLASS_NETWORK_ETHERNET << 8,
+ reverse_probe ? 0xfe - pci_index : pci_index,
+ &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL)
+ if (reverse_probe)
+ continue;
+ else
+ break;
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_DEVICE_ID, &device);
+
+ for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++)
+ if (vendor == tulip_tbl[chip_idx].vendor_id &&
+ device == tulip_tbl[chip_idx].device_id)
+ break;
+ if (tulip_tbl[chip_idx].chip_name == 0) {
+ if (vendor == PCI_VENDOR_ID_DEC ||
+ vendor == PCI_VENDOR_ID_LITEON)
+ printk(KERN_INFO "Unknown Tulip-style PCI ethernet chip type"
+ " %4.4x %4.4x"" detected: not configured.\n",
+ vendor, device);
+ continue;
+ }
#if LINUX_VERSION_CODE >= 0x20155
- pdev = pci_find_slot(pci_bus, pci_device_fn);
- pci_irq_line = pdev->irq;
- pci_ioaddr = pdev->base_address[0];
+ pci_ioaddr = pci_find_slot(pci_bus, pci_device_fn)->base_address[0];
#else
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_INTERRUPT_LINE, &pci_irq_line);
- pcibios_read_config_dword(pci_bus, pci_device_fn,
- PCI_BASE_ADDRESS_0, &pci_ioaddr);
+ pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0,
+ &pci_ioaddr);
#endif
- /* Remove I/O space marker in bit 0. */
- pci_ioaddr &= ~3;
-
- if (vendor != PCI_VENDOR_ID_DEC
- && vendor != PCI_VENDOR_ID_LITEON)
- continue;
- if (vendor == PCI_VENDOR_ID_LITEON)
- device = PCI_DEVICE_ID_PNIC_X;
-
- for (chip_idx = 0; tulip_tbl[chip_idx].chip_name; chip_idx++)
- if (device == tulip_tbl[chip_idx].device_id)
- break;
- if (tulip_tbl[chip_idx].chip_name == 0) {
- printk(KERN_INFO "Unknown Digital PCI ethernet chip type"
- " %4.4x"" detected: not configured.\n", device);
- continue;
- }
- if (tulip_debug > 2)
- printk(KERN_DEBUG "Found DEC PCI Tulip at I/O %#x, IRQ %d.\n",
- pci_ioaddr, pci_irq_line);
+ /* Remove I/O space marker in bit 0. */
+ pci_ioaddr &= ~3;
- if (check_region(pci_ioaddr, TULIP_TOTAL_SIZE))
- continue;
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "Found %s at I/O %#lx.\n",
+ tulip_tbl[chip_idx].chip_name, pci_ioaddr);
+
+ if (check_region(pci_ioaddr, tulip_tbl[chip_idx].io_size))
+ continue;
+
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, &pci_command);
+ new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+ if (pci_command != new_command) {
+ printk(KERN_INFO " The PCI BIOS has not enabled this"
+ " device! Updating PCI command %4.4x->%4.4x.\n",
+ pci_command, new_command);
+ pcibios_write_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, new_command);
+ }
-#ifdef MODULE
- dev = tulip_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
- cards_found);
-#else
- dev = tulip_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx, -1);
-#endif
+ dev = tulip_probe1(pci_bus, pci_device_fn, dev, chip_idx, cards_found);
- if (dev) {
- /* Get and check the bus-master and latency values. */
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
- if ( ! (pci_command & PCI_COMMAND_MASTER)) {
- printk(KERN_INFO " PCI Master Bit has not been set! Setting...\n");
- pci_command |= PCI_COMMAND_MASTER;
- pcibios_write_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, pci_command);
- }
- pcibios_read_config_byte(pci_bus, pci_device_fn,
- PCI_LATENCY_TIMER, &pci_latency);
- if (pci_latency < 10) {
- printk(KERN_INFO " PCI latency timer (CFLT) is unreasonably"
- " low at %d. Setting to 64 clocks.\n", pci_latency);
+ /* Get and check the bus-master and latency values. */
+ if (dev) {
+ unsigned char pci_latency;
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_LATENCY_TIMER, &pci_latency);
+ if (pci_latency < 10) {
+ printk(KERN_INFO " PCI latency timer (CFLT) is "
+ "unreasonably low at %d. Setting to 64 clocks.\n",
+ pci_latency);
pcibios_write_config_byte(pci_bus, pci_device_fn,
PCI_LATENCY_TIMER, 64);
- } else if (tulip_debug > 1)
- printk(KERN_INFO " PCI latency timer (CFLT) is %#x.\n",
- pci_latency);
- /* Bring the 21143 out power-down mode. */
- if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
+ } else if (tulip_debug > 1)
+ printk(KERN_INFO " PCI latency timer (CFLT) is %#x, "
+ " PCI command is %4.4x.\n",
+ pci_latency, new_command);
+ /* Bring the 21143 out power-down mode. */
+ if (device == PCI_DEVICE_ID_DEC_TULIP_21142)
pcibios_write_config_dword(pci_bus, pci_device_fn,
- 0x40, 0x40000000);
- dev = 0;
- cards_found++;
- }
+ 0x40, 0x40000000);
+ dev = 0;
+ cards_found++;
}
}
return cards_found ? 0 : -ENODEV;
}
-static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
+static struct device *tulip_probe1(int pci_bus, int pci_device_fn,
+ struct device *dev,
int chip_id, int board_idx)
{
static int did_version = 0; /* Already printed version info. */
struct tulip_private *tp;
+ long ioaddr;
+ int irq;
/* See note below on the multiport cards. */
static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
static int last_irq = 0;
+ static int multiport_cnt = 0; /* For four-port boards w/one EEPROM */
int i;
unsigned short sum;
@@ -572,7 +566,25 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
dev = init_etherdev(dev, 0);
- printk(KERN_INFO "%s: %s at %#3x,",
+#if LINUX_VERSION_CODE >= 0x20155
+ irq = pci_find_slot(pci_bus, pci_device_fn)->irq;
+ ioaddr = pci_find_slot(pci_bus, pci_device_fn)->base_address[0];
+#else
+ {
+ u8 pci_irq_line;
+ u32 pci_ioaddr;
+ pcibios_read_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, &pci_irq_line);
+ pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0,
+ &pci_ioaddr);
+ irq = pci_irq_line;
+ ioaddr = pci_ioaddr;
+ }
+#endif
+ /* Remove I/O space marker in bit 0. */
+ ioaddr &= ~3;
+
+ printk(KERN_INFO "%s: %s at %#3lx,",
dev->name, tulip_tbl[chip_id].chip_name, ioaddr);
/* Stop the chip's Tx and Rx processes. */
@@ -629,6 +641,10 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
for (i = 0; i < 8; i ++)
if (ee_data[i] != ee_data[16+i])
sa_offset = 20;
+ if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
+ sa_offset = 2; /* Grrr, damn Matrox boards. */
+ multiport_cnt = 4;
+ }
for (i = 0; i < 6; i ++) {
dev->dev_addr[i] = ee_data[i + sa_offset];
sum += ee_data[i + sa_offset];
@@ -655,13 +671,15 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
irq = last_irq;
#endif
}
+
for (i = 0; i < 6; i++)
printk(" %2.2x", last_phys_addr[i] = dev->dev_addr[i]);
printk(", IRQ %d.\n", irq);
last_irq = irq;
/* We do a request_region() only to register /proc/ioports info. */
- request_region(ioaddr, TULIP_TOTAL_SIZE, tulip_tbl[chip_id].chip_name);
+ /* Note that proper size is tulip_tbl[chip_id].chip_name, but... */
+ request_region(ioaddr, TULIP_TOTAL_SIZE, dev->name);
dev->base_addr = ioaddr;
dev->irq = irq;
@@ -671,11 +689,11 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
memset(tp, 0, sizeof(*tp));
dev->priv = tp;
-#ifdef MODULE
tp->next_module = root_tulip_dev;
root_tulip_dev = dev;
-#endif
+ tp->pci_bus = pci_bus;
+ tp->pci_dev_fn = pci_device_fn;
tp->chip_id = chip_id;
#ifdef TULIP_FULL_DUPLEX
@@ -690,36 +708,64 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
#endif
/* The lower four bits are the media type. */
- if (board_idx >= 0) {
- tp->full_duplex = (options[board_idx]&16) || full_duplex[board_idx]>0;
- if (tp->full_duplex)
- tp->full_duplex_lock = 1;
+ if (board_idx >= 0 && board_idx < MAX_UNITS) {
tp->default_port = options[board_idx] & 15;
- if (tp->default_port)
- tp->medialock = 1;
+ if ((options[board_idx] & 0x90) || full_duplex[board_idx] > 0)
+ tp->full_duplex = 1;
if (mtu[board_idx] > 0)
dev->mtu = mtu[board_idx];
}
+ if (dev->mem_start)
+ tp->default_port = dev->mem_start;
+ if (tp->default_port) {
+ tp->medialock = 1;
+ if (media_cap[tp->default_port] & MediaAlwaysFD)
+ tp->full_duplex = 1;
+ }
+ if (tp->full_duplex)
+ tp->full_duplex_lock = 1;
/* This is logically part of probe1(), but too complex to write inline. */
- if (chip_id != DC21040 && chip_id != LC82C168)
+ if (tulip_tbl[chip_id].flags & HAS_MEDIA_TABLE)
parse_eeprom(dev);
- if (tp->mtable && tp->mtable->has_mii) {
+ if (media_cap[tp->default_port] & MediaIsMII) {
+ u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
+ tp->to_advertise = media2advert[tp->default_port - 9];
+ } else
+ tp->to_advertise = 0x03e1;
+
+ if ((tp->mtable && tp->mtable->has_mii) ||
+ ( ! tp->mtable && (tulip_tbl[tp->chip_id].flags & HAS_MII))) {
int phy, phy_idx;
/* Find the connected MII xcvrs.
Doing this in open() would allow detecting external xcvrs later,
but takes much time. */
for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
phy++) {
- int mii_status = mdio_read(ioaddr, phy, 0);
- if (mii_status != 0xffff && mii_status != 0x0000) {
- tp->phys[phy_idx++] = phy;
- printk(KERN_INFO "%s: MII transceiver found at MDIO address %d.\n",
- dev->name, phy);
+ int mii_status = mdio_read(dev, phy, 1);
+ if (mii_status != 0xffff && mii_status != 0x0000) {
+ int mii_reg0 = mdio_read(dev, phy, 0);
+ int reg4 = ((mii_status>>6) & tp->to_advertise) | 1;
+ tp->phys[phy_idx] = phy;
+ tp->advertising[phy_idx++] = reg4;
+ printk(KERN_INFO "%s: MII transceiver found at MDIO address "
+ "%d, config %4.4x status %4.4x.\n",
+ dev->name, phy, mii_reg0, mii_status);
+ if (1 || (media_cap[tp->default_port] & MediaIsMII)) {
+ printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d,"
+ " previously advertising %4.4x.\n",
+ dev->name, reg4, phy, mdio_read(dev, phy, 4));
+ mdio_write(dev, phy, 4, reg4);
+ }
+ /* Enable autonegotiation: some boards default to off. */
+ mdio_write(dev, phy, 0, mii_reg0 |
+ (tp->full_duplex ? 0x1100 : 0x1000) |
+ (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
}
}
- if (phy_idx == 0) {
+ tp->mii_cnt = phy_idx;
+ if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
dev->name);
tp->phys[0] = 1;
@@ -731,11 +777,11 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
dev->hard_start_xmit = &tulip_start_xmit;
dev->stop = &tulip_close;
dev->get_stats = &tulip_get_stats;
-#ifdef HAVE_MULTICAST
- dev->set_multicast_list = &set_multicast_list;
+#ifdef HAVE_PRIVATE_IOCTL
+ dev->do_ioctl = &private_ioctl;
#endif
-#ifdef CONFIG_NET_FASTROUTE
- dev->accept_fastpath = tulip_accept_fastpath;
+#ifdef HAVE_MULTICAST
+ dev->set_multicast_list = &set_rx_mode;
#endif
/* Reset the xcvr interface and turn on heartbeat. */
@@ -744,20 +790,37 @@ static struct device *tulip_probe1(struct device *dev, int ioaddr, int irq,
outl(0x00000000, ioaddr + CSR13);
outl(0xFFFFFFFF, ioaddr + CSR14);
outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
- outl(inl(ioaddr + CSR6) | 0x200, ioaddr + CSR6);
+ outl(inl(ioaddr + CSR6) | 0x0200, ioaddr + CSR6);
outl(0x0000EF05, ioaddr + CSR13);
break;
- case DC21140: case DC21142:
- if (tp->mtable)
- outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
- break;
case DC21040:
outl(0x00000000, ioaddr + CSR13);
outl(0x00000004, ioaddr + CSR13);
break;
+ case DC21140: default:
+ if (tp->mtable)
+ outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
+ break;
+ case DC21142:
+ outl(0x82420200, ioaddr + CSR6);
+ outl(0x0001, ioaddr + CSR13);
+ outl(0x0003FFFF, ioaddr + CSR14);
+ outl(0x0008, ioaddr + CSR15);
+ outl(0x0001, ioaddr + CSR13);
+ outl(0x1301, ioaddr + CSR12); /* Start NWay. */
+ break;
case LC82C168:
- outl(0x33, ioaddr + CSR12);
- outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+ if ( ! tp->mii_cnt) {
+ outl(0x00420000, ioaddr + CSR6);
+ outl(0x30, ioaddr + CSR12);
+ outl(0x0001F078, ioaddr + 0xB8);
+ outl(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
+ }
+ break;
+ case MX98713: case MX98715: case MX98725:
+ outl(0x00000000, ioaddr + CSR6);
+ outl(0x000711C0, ioaddr + CSR14); /* Turn on NWay. */
+ outl(0x00000001, ioaddr + CSR13);
break;
}
@@ -782,7 +845,9 @@ static struct fixups {
{"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x021f,
0x0000, 0x009E, /* 10baseT */
0x0903, 0x006D, /* 100baseTx */ }},
- {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x013f,
+ {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x033f,
+ 0x0107, 0x8021, /* 100baseFx */
+ 0x0108, 0x8021, /* 100baseFx-FD */
0x0103, 0x006D, /* 100baseTx */ }},
{"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0313,
0x1001, 0x009E, /* 10base2, CSR12 0x10*/
@@ -796,9 +861,15 @@ static struct fixups {
{0, 0, 0, 0, {}}};
static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
- "21142 non-MII PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
+ "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
#define EEPROM_SIZE 128
+#if defined(__i386__)
+#define get_u16(ptr) (*(u16 *)(ptr))
+#else
+#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
+#endif
+
static void parse_eeprom(struct device *dev)
{
/* The last media info list parsed, for multiport boards. */
@@ -806,7 +877,7 @@ static void parse_eeprom(struct device *dev)
static unsigned char *last_ee_data = NULL;
static int controller_index = 0;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
unsigned char *ee_data = tp->eeprom;
int i;
@@ -870,30 +941,45 @@ static void parse_eeprom(struct device *dev)
}
subsequent_board:
- if (tp->chip_id == DC21041) {
+ if (ee_data[27] == 0) { /* No valid media table. */
+ } else if (tp->chip_id == DC21041) {
unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3];
- short media = *(u16 *)p;
- int count = p[2];
+ short media;
+ int count;
+
+ media = get_u16(p);
+ p += 2;
+ count = *p++;
printk(KERN_INFO "%s:21041 Media information at %d, default media "
"%4.4x (%s).\n", dev->name, ee_data[27], media,
media & 0x0800 ? "Autosense" : medianame[media & 15]);
for (i = 0; i < count; i++) {
- unsigned char media_code = p[3 + i*7];
- u16 *csrvals = (u16 *)&p[3 + i*7 + 1];
- printk(KERN_INFO "%s: 21041 media %2.2x (%s),"
- " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n",
- dev->name, media_code & 15, medianame[media_code & 15],
- csrvals[0], csrvals[1], csrvals[2]);
+ unsigned char media_code = *p++;
+ u16 csrvals[3];
+ int idx;
+ for (idx = 0; idx < 3; idx++) {
+ csrvals[idx] = get_u16(p);
+ p += 2;
+ }
+ if (media_code & 0x40) {
+ printk(KERN_INFO "%s: 21041 media %2.2x (%s),"
+ " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n",
+ dev->name, media_code & 15, medianame[media_code & 15],
+ csrvals[0], csrvals[1], csrvals[2]);
+ } else
+ printk(KERN_INFO "%s: 21041 media #%d, %s.\n",
+ dev->name, media_code & 15, medianame[media_code & 15]);
}
} else {
unsigned char *p = (void *)ee_data + ee_data[27];
unsigned char csr12dir = 0;
int count;
struct mediatable *mtable;
- u16 media = *((u16 *)p)++;
+ u16 media = get_u16(p);
- if (tp->chip_id == DC21140)
+ p += 2;
+ if (tulip_tbl[tp->chip_id].flags & CSR12_IN_SROM)
csr12dir = *p++;
count = *p++;
mtable = (struct mediatable *)
@@ -905,7 +991,7 @@ subsequent_board:
mtable->defaultmedia = media;
mtable->leafcount = count;
mtable->csr12dir = csr12dir;
- mtable->has_mii = 0;
+ mtable->has_nonmii = mtable->has_mii = 0;
printk(KERN_INFO "%s: EEPROM default media type %s.\n", dev->name,
media & 0x0800 ? "Autosense" : medianame[media & 15]);
@@ -916,14 +1002,18 @@ subsequent_board:
leaf->type = 0;
leaf->media = p[0] & 0x3f;
leaf->leafdata = p;
+ if ((p[2] & 0x61) == 0x01) /* Bogus, but Znyx boards do it. */
+ mtable->has_mii = 1;
p += 4;
} else {
leaf->type = p[1];
if (p[1] & 1) {
mtable->has_mii = 1;
leaf->media = 11;
- } else
+ } else {
+ mtable->has_nonmii = 1;
leaf->media = p[2] & 0x0f;
+ }
leaf->leafdata = p + 2;
p += (p[0] & 0x3f) + 1;
}
@@ -966,11 +1056,11 @@ subsequent_board:
#define EE_READ_CMD (6 << 6)
#define EE_ERASE_CMD (7 << 6)
-static int read_eeprom(int ioaddr, int location)
+static int read_eeprom(long ioaddr, int location)
{
int i;
unsigned short retval = 0;
- int ee_addr = ioaddr + CSR9;
+ long ee_addr = ioaddr + CSR9;
int read_cmd = location | EE_READ_CMD;
outl(EE_ENB & ~EE_CS, ee_addr);
@@ -1001,6 +1091,16 @@ static int read_eeprom(int ioaddr, int location)
return retval;
}
+/* MII transceiver control section.
+ Read and write the MII registers using software-generated serial
+ MDIO protocol. See the MII specifications or DP83840A data sheet
+ for details. */
+
+/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
+ met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+ "overclocking" issues or future 66Mhz PCI. */
+#define mdio_delay() inl(mdio_addr)
+
/* Read and write the MII registers using software-generated serial
MDIO protocol. It is just different enough from the EEPROM protocol
to not share code. The maxium data clock rate is 2.5 Mhz. */
@@ -1010,18 +1110,24 @@ static int read_eeprom(int ioaddr, int location)
#define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */
#define MDIO_ENB_IN 0x40000
#define MDIO_DATA_READ 0x80000
-#ifdef _LINUX_DELAY_H
-#define mdio_delay() udelay(1)
-#else
-#define mdio_delay() __SLOW_DOWN_IO
-#endif
-static int mdio_read(int ioaddr, int phy_id, int location)
+static int mdio_read(struct device *dev, int phy_id, int location)
{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
int i;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
- unsigned short retval = 0;
- int mdio_addr = ioaddr + CSR9;
+ int retval = 0;
+ long mdio_addr = dev->base_addr + CSR9;
+
+ if (tp->chip_id == LC82C168) {
+ long ioaddr = dev->base_addr;
+ int i = 1000;
+ outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
+ while (--i > 0)
+ if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
+ return retval & 0xffff;
+ return 0xffff;
+ }
/* Establish sync by sending at least 32 logic ones. */
for (i = 32; i >= 0; i--) {
@@ -1031,60 +1137,78 @@ static int mdio_read(int ioaddr, int phy_id, int location)
mdio_delay();
}
/* Shift the read command bits out. */
- for (i = 17; i >= 0; i--) {
+ for (i = 15; i >= 0; i--) {
int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
- outl(dataval, mdio_addr);
- mdio_delay();
- outl(dataval | MDIO_SHIFT_CLK, mdio_addr);
+ outl(MDIO_ENB | dataval, mdio_addr);
mdio_delay();
- outl(dataval, mdio_addr);
+ outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
- outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
- mdio_delay();
- outl(MDIO_ENB_IN, mdio_addr);
-
- for (i = 16; i > 0; i--) {
- outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
- mdio_delay();
- retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
+ /* Read the two transition, 16 data, and wire-idle bits. */
+ for (i = 19; i > 0; i--) {
outl(MDIO_ENB_IN, mdio_addr);
mdio_delay();
- }
- /* Clear out extra bits. */
- for (i = 16; i > 0; i--) {
+ retval = (retval << 1) | ((inl(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
- outl(MDIO_ENB_IN, mdio_addr);
- mdio_delay();
}
- return retval;
+ return (retval>>1) & 0xffff;
}
-#ifdef CONFIG_NET_HW_FLOWCONTROL
-/* Enable receiver */
-
-void tulip_xon(struct device *dev)
+static void mdio_write(struct device *dev, int phy_id, int location, int value)
{
- struct tulip_private *lp = (struct tulip_private *)dev->priv;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ int i;
+ int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
+ long mdio_addr = dev->base_addr + CSR9;
+
+ if (tp->chip_id == LC82C168) {
+ long ioaddr = dev->base_addr;
+ int i = 1000;
+ outl(cmd, ioaddr + 0xA0);
+ do
+ if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
+ break;
+ while (--i > 0);
+ return;
+ }
- clear_bit(lp->fc_bit, &netdev_fc_xoff);
- if (dev->start)
- outl(lp->csr6 | 0x2002, dev->base_addr + CSR6);
+ /* Establish sync by sending 32 logic ones. */
+ for (i = 32; i >= 0; i--) {
+ outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Shift the command bits out. */
+ for (i = 31; i >= 0; i--) {
+ int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
+ outl(MDIO_ENB | dataval, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ /* Clear out extra bits. */
+ for (i = 2; i > 0; i--) {
+ outl(MDIO_ENB_IN, mdio_addr);
+ mdio_delay();
+ outl(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
+ mdio_delay();
+ }
+ return;
}
-#endif
static int
tulip_open(struct device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int i = 0;
/* On some chip revs we must set the MII/SYM port before the reset!? */
- if (tp->mtable && tp->mtable->has_mii)
+ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii))
outl(0x00040000, ioaddr + CSR6);
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
@@ -1106,31 +1230,30 @@ tulip_open(struct device *dev)
Tx and Rx queues and the address filter list. */
#if defined(__alpha__)
/* ToDo: Alpha setting could be better. */
- outl(0x00200000 | 0xE000, ioaddr + CSR0);
+ outl(0x01A00000 | 0xE000, ioaddr + CSR0);
#elif defined(__powerpc__)
- outl(0x00200080 | 0x8000, ioaddr + CSR0);
+ outl(0x01A00080 | 0x8000, ioaddr + CSR0);
#elif defined(__i386__)
#if defined(MODULE)
/* When a module we don't have 'x86' to check. */
- outl(0x00200000 | 0x4800, ioaddr + CSR0);
+ outl(0x01A00000 | 0x4800, ioaddr + CSR0);
#else
-#ifndef ORIGINAL_TEXT
-#define x86 (boot_cpu_data.x86)
+#if (LINUX_VERSION_CODE > 0x2014c)
+#define x86 boot_cpu_data.x86
#endif
- outl(0x00200000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);
+ outl(0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000), ioaddr + CSR0);
if (x86 <= 4)
printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "
"alignment to %x.\n", dev->name,
- 0x00200000 | (x86 <= 4 ? 0x4800 : 0x8000));
+ 0x01A00000 | (x86 <= 4 ? 0x4800 : 0x8000));
#endif
#else
- outl(0x00200000 | 0x4800, ioaddr + CSR0);
+ outl(0x01A00000 | 0x4800, ioaddr + CSR0);
#warning Processor architecture undefined!
#endif
#ifdef SA_SHIRQ
- if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ,
- tulip_tbl[tp->chip_id].chip_name, dev)) {
+ if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev)) {
return -EAGAIN;
}
#else
@@ -1178,7 +1301,7 @@ tulip_open(struct device *dev)
outl(virt_to_bus(tp->tx_ring), ioaddr + CSR4);
if (dev->if_port == 0)
- dev->if_port = tp->default_port;
+ dev->if_port = tp->default_port;
if (tp->chip_id == DC21041 && dev->if_port > 4)
/* Invalid: Select initial TP, autosense, autonegotiate. */
dev->if_port = 4;
@@ -1186,14 +1309,16 @@ tulip_open(struct device *dev)
/* Allow selecting a default media. */
if (tp->mtable == NULL)
goto media_picked;
- if (dev->if_port)
+ if (dev->if_port) {
+ int looking_for = media_cap[dev->if_port] & MediaIsMII ? 11 :
+ (dev->if_port == 12 ? 0 : dev->if_port);
for (i = 0; i < tp->mtable->leafcount; i++)
- if (tp->mtable->mleaf[i].media ==
- (dev->if_port == 12 ? 0 : dev->if_port)) {
- printk(KERN_INFO "%s: Using user-specified media %s.\n",
- dev->name, medianame[dev->if_port]);
- goto media_picked;
- }
+ if (tp->mtable->mleaf[i].media == looking_for) {
+ printk(KERN_INFO "%s: Using user-specified media %s.\n",
+ dev->name, medianame[dev->if_port]);
+ goto media_picked;
+ }
+ }
if ((tp->mtable->defaultmedia & 0x0800) == 0)
for (i = 0; i < tp->mtable->leafcount; i++)
if (tp->mtable->mleaf[i].media == (tp->mtable->defaultmedia & 15)) {
@@ -1201,55 +1326,61 @@ tulip_open(struct device *dev)
dev->name, medianame[tp->mtable->mleaf[i].media]);
goto media_picked;
}
+ /* Start sensing first non-full-duplex media. */
for (i = tp->mtable->leafcount - 1;
- (media_fd[tp->mtable->mleaf[i].media] & 2) && i > 0; i--)
+ (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
;
media_picked:
- tp->cur_index = i;
tp->csr6 = 0;
- select_media(dev, 1);
+ tp->cur_index = i;
+ if (dev->if_port == 0 && tp->chip_id == DC21142) {
+ tp->csr6 = 0x82420200;
+ outl(0x0003FFFF, ioaddr + CSR14);
+ outl(0x0008, ioaddr + CSR15);
+ outl(0x0001, ioaddr + CSR13);
+ outl(0x1301, ioaddr + CSR12);
+ } else if (tp->chip_id == LC82C168 && tp->mii_cnt && ! tp->medialock) {
+ dev->if_port = 11;
+ tp->csr6 = 0x816C0000 | (tp->full_duplex ? 0x0200 : 0);
+ outl(0x0001, ioaddr + CSR15);
+ } else
+ select_media(dev, 1);
/* Start the chip's Tx to process setup frame. */
outl(tp->csr6, ioaddr + CSR6);
outl(tp->csr6 | 0x2000, ioaddr + CSR6);
dev->tbusy = 0;
- dev->interrupt = 0;
+ tp->interrupt = 0;
dev->start = 1;
-
/* Enable interrupts by setting the interrupt mask. */
- outl(0x0001ebef, ioaddr + CSR7);
+ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
+ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
outl(tp->csr6 | 0x2002, ioaddr + CSR6);
outl(0, ioaddr + CSR2); /* Rx poll demand */
if (tulip_debug > 2) {
- printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR13 %8.8x.\n",
+ printk(KERN_DEBUG "%s: Done tulip_open(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
dev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
- inl(ioaddr + CSR13));
+ inl(ioaddr + CSR6));
}
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
init_timer(&tp->timer);
- tp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
+ tp->timer.expires = RUN_AT(5*HZ);
tp->timer.data = (unsigned long)dev;
- tp->timer.function = &tulip_timer; /* timer handler */
+ tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
add_timer(&tp->timer);
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- tp->fc_bit = netdev_register_fc(dev, tulip_xon);
-#endif
-#ifdef CONFIG_NET_FASTROUTE
- dev->tx_semaphore = 1;
-#endif
return 0;
}
/* Set up the transceiver control registers for the selected media type. */
static void select_media(struct device *dev, int startup)
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
struct mediatable *mtable = tp->mtable;
u32 new_csr6;
@@ -1261,8 +1392,8 @@ static void select_media(struct device *dev, int startup)
switch (mleaf->type) {
case 0: /* 21140 non-MII xcvr. */
if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver with control"
- " setting %2.2x.\n",
+ printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver"
+ " with control setting %2.2x.\n",
dev->name, p[1]);
dev->if_port = p[0];
if (startup)
@@ -1270,26 +1401,11 @@ static void select_media(struct device *dev, int startup)
outl(p[1], ioaddr + CSR12);
new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
break;
- case 1:
- if (startup) {
- outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
- dev->if_port = 11;
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: Doing a reset sequence of length %d.\n",
- dev->name, p[2 + p[1]]);
- for (i = 0; i < p[2 + p[1]]; i++)
- outl(p[3 + p[1] + i], ioaddr + CSR12);
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s Doing a transceiver setup sequence of length %d.\n",
- dev->name, p[1]);
- for (i = 0; i < p[1]; i++)
- outl(p[2 + i], ioaddr + CSR12);
- }
- check_mii = 1;
- new_csr6 = 0x020C0000;
- break;
case 2: case 4: {
- u16 *setup = (u16*)&p[1];
+ u16 setup[3];
+ for (i = 0; i < 3; i++)
+ setup[i] = get_u16(&p[i*2 + 1]);
+
dev->if_port = p[0] & 15;
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: 21142 non-MII %s transceiver control %4.4x/%4.4x.\n",
@@ -1299,59 +1415,74 @@ static void select_media(struct device *dev, int startup)
outl(setup[1], ioaddr + CSR14);
outl(setup[2], ioaddr + CSR15);
outl(setup[0], ioaddr + CSR13);
- setup += 3;
- } else {
+ for (i = 0; i < 3; i++) /* Re-fill setup[] */
+ setup[i] = get_u16(&p[i*2 + 7]);
+ } else if (dev->if_port <= 4) {
outl(0, ioaddr + CSR13);
outl(t21142_csr14[dev->if_port], ioaddr + CSR14);
outl(t21142_csr15[dev->if_port], ioaddr + CSR15);
outl(t21142_csr13[dev->if_port], ioaddr + CSR13);
+ } else {
+ outl(0, ioaddr + CSR14);
+ outl(8, ioaddr + CSR15);
+ outl(0, ioaddr + CSR13);
}
outl(setup[0]<<16, ioaddr + CSR15); /* Direction */
outl(setup[1]<<16, ioaddr + CSR15); /* Data */
if (mleaf->type == 4)
- new_csr6 = 0x02000000 | ((setup[2] & 0x71) << 18);
+ new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
else
new_csr6 = 0x82420000;
break;
}
- case 3: {
+ case 1: case 3: {
+ int phy_num = p[0];
int init_length = p[1];
- u16 * init_sequence = (u16*)(p + 2);
- int reset_length = p[2 + init_length*2];
- u16 * reset_sequence = (u16*)&p[3 + init_length*2];
+ u16 *misc_info;
+ u16 to_advertise;
dev->if_port = 11;
- if (startup) {
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: Doing a 21142 reset sequence of length %d.\n",
- dev->name, reset_length);
- for (i = 0; i < reset_length; i++)
- outl(reset_sequence[i] << 16, ioaddr + CSR15);
- }
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: Doing a 21142 xcvr setup sequence of length %d.\n",
- dev->name, init_length);
- for (i = 0; i < init_length; i++)
- outl(init_sequence[i] << 16, ioaddr + CSR15);
check_mii = 1;
- new_csr6 = 0x020C0000;
+ new_csr6 = 0x020E0000;
+ if (mleaf->type == 3) { /* 21142 */
+ u16 *init_sequence = (u16*)(p+2);
+ u16 *reset_sequence = &((u16*)(p+3))[init_length];
+ int reset_length = p[2 + init_length*2];
+ misc_info = reset_sequence + reset_length;
+ if (startup)
+ for (i = 0; i < reset_length; i++)
+ outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
+ for (i = 0; i < init_length; i++)
+ outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
+ } else {
+ u8 *init_sequence = p + 2;
+ u8 *reset_sequence = p + 3 + init_length;
+ int reset_length = p[2 + init_length];
+ misc_info = (u16*)(reset_sequence + reset_length);
+ if (startup) {
+ outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
+ for (i = 0; i < reset_length; i++)
+ outl(reset_sequence[i], ioaddr + CSR12);
+ }
+ for (i = 0; i < init_length; i++)
+ outl(init_sequence[i], ioaddr + CSR12);
+ }
+ to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;
+ tp->advertising[phy_num] = to_advertise;
+ if (tulip_debug > 1 || 1)
+ printk(KERN_DEBUG "%s: Advertising %4.4x on PHY %d (%d).\n",
+ dev->name, to_advertise, phy_num, tp->phys[phy_num]);
+ /* Bogus: put in by a committee? */
+ mdio_write(dev, tp->phys[phy_num], 4, to_advertise);
break;
}
default:
- new_csr6 = 0x020C0000;
+ new_csr6 = 0x020E0000;
}
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n",
dev->name, medianame[dev->if_port],
inl(ioaddr + CSR12) & 0xff);
- } else if (tp->chip_id == DC21140) {
- /* Set media type to MII @ 100mbps: 0x020C0000 */
- new_csr6 = 0x020C0000;
- dev->if_port = 11;
- if (tulip_debug > 1) {
- printk(KERN_DEBUG "%s: Unknown media control, assuming MII, CSR12 %2.2x.\n",
- dev->name, inl(ioaddr + CSR12) & 0xff);
- }
} else if (tp->chip_id == DC21041) {
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n",
@@ -1363,14 +1494,24 @@ static void select_media(struct device *dev, int startup)
outl(t21041_csr13[dev->if_port], ioaddr + CSR13);
new_csr6 = 0x80020000;
} else if (tp->chip_id == LC82C168) {
- if (startup)
- dev->if_port = 3;
+ if (startup && ! tp->medialock)
+ dev->if_port = tp->mii_cnt ? 11 : 0;
if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: LiteOn PHY status is %3.3x, CSR12 %4.4x,"
+ printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, CSR12 %4.4x,"
" media %s.\n",
dev->name, inl(ioaddr + 0xB8), inl(ioaddr + CSR12),
medianame[dev->if_port]);
- if (dev->if_port == 3 || dev->if_port == 5) {
+ if (tp->mii_cnt) {
+ new_csr6 = 0x812C0000;
+ outl(0x0001, ioaddr + CSR15);
+ outl(0x0201B07A, ioaddr + 0xB8);
+ } else if (startup) {
+ /* Start with 10mbps to do autonegotiation. */
+ outl(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ outl(0x0001B078, ioaddr + 0xB8);
+ outl(0x0201B078, ioaddr + 0xB8);
+ } else if (dev->if_port == 3 || dev->if_port == 5) {
outl(0x33, ioaddr + CSR12);
new_csr6 = 0x01860000;
if (startup)
@@ -1382,7 +1523,7 @@ static void select_media(struct device *dev, int startup)
new_csr6 = 0x00420000;
outl(0x1F078, ioaddr + 0xB8);
}
- } else { /* 21040 */
+ } else if (tp->chip_id == DC21040) { /* 21040 */
/* Turn on the xcvr interface. */
int csr12 = inl(ioaddr + CSR12);
if (tulip_debug > 1)
@@ -1393,6 +1534,23 @@ static void select_media(struct device *dev, int startup)
outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
outl(dev->if_port ? 0x0000000C : 0x00000004, ioaddr + CSR13);
+ } else { /* Unknown chip type with no media table. */
+ if (tp->default_port == 0)
+ if (tp->mii_cnt) {
+ dev->if_port = 11;
+ } else
+ dev->if_port = 3;
+ if (media_cap[dev->if_port] & MediaIsMII) {
+ new_csr6 = 0x020E0000;
+ } else if (media_cap[dev->if_port] & MediaIsFx) {
+ new_csr6 = 0x028600000;
+ } else
+ new_csr6 = 0x038600000;
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: No media description table, assuming "
+ "%s transceiver, CSR12 %2.2x.\n",
+ dev->name, medianame[dev->if_port],
+ inl(ioaddr + CSR12));
}
tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
@@ -1403,7 +1561,7 @@ static void tulip_timer(unsigned long data)
{
struct device *dev = (struct device *)data;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
u32 csr12 = inl(ioaddr + CSR12);
int next_tick = 0;
@@ -1467,167 +1625,366 @@ static void tulip_timer(unsigned long data)
break;
}
break;
- case LC82C168: {
+ case DC21140: case DC21142: case MX98713: default: {
+ struct medialeaf *mleaf;
+ unsigned char *p;
+ if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */
+ /* Not much that can be done.
+ Assume this a generic MII or SYM transceiver. */
+ next_tick = 60*HZ;
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x "
+ "CSR12 0x%2.2x.\n",
+ dev->name, inl(ioaddr + CSR6), csr12 & 0xff);
+ break;
+ }
+ mleaf = &tp->mtable->mleaf[tp->cur_index];
+ p = mleaf->leafdata;
+ switch (mleaf->type) {
+ case 0: case 4: {
+ /* Type 0 serial or 4 SYM transceiver. Check the link beat bit. */
+ int offset = mleaf->type == 4 ? 5 : 2;
+ s8 bitnum = p[offset];
+ if (p[offset+1] & 0x80) {
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG"%s: Transceiver monitor tick "
+ "CSR12=%#2.2x, no media sense.\n",
+ dev->name, csr12);
+ if (mleaf->type == 4) {
+ if (mleaf->media == 3 && (csr12 & 0x02))
+ goto select_next_media;
+ }
+ break;
+ }
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x"
+ " bit %d is %d, expecting %d.\n",
+ dev->name, csr12, (bitnum >> 1) & 7,
+ (csr12 & (1 << ((bitnum >> 1) & 7))) != 0,
+ (bitnum >= 0));
+ /* Check that the specified bit has the proper value. */
+ if ((bitnum < 0) !=
+ ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) {
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name,
+ medianame[mleaf->media]);
+ if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */
+ goto actually_mii;
+ break;
+ }
+ if (tp->medialock)
+ break;
+ select_next_media:
+ if (--tp->cur_index < 0) {
+ /* We start again, but should instead look for default. */
+ tp->cur_index = tp->mtable->leafcount - 1;
+ }
+ dev->if_port = tp->mtable->mleaf[tp->cur_index].media;
+ if (media_cap[dev->if_port] & MediaIsFD)
+ goto select_next_media; /* Skip FD entries. */
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: No link beat on media %s,"
+ " trying transceiver type %s.\n",
+ dev->name, medianame[mleaf->media & 15],
+ medianame[tp->mtable->mleaf[tp->cur_index].media]);
+ select_media(dev, 0);
+ /* Restart the transmit process. */
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ next_tick = (24*HZ)/10;
+ break;
+ }
+ case 1: case 3: { /* 21140, 21142 MII */
+ int mii_reg1, mii_reg5;
+ actually_mii:
+ mii_reg1 = mdio_read(dev, tp->phys[0], 1);
+ mii_reg5 = mdio_read(dev, tp->phys[0], 5);
+ if (tulip_debug > 1)
+ printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
+ "%4.4x, CSR12 %2.2x, %cD.\n",
+ dev->name, mii_reg1, mii_reg5, csr12,
+ tp->full_duplex ? 'F' : 'H');
+ if (mii_reg1 != 0xffff && (mii_reg1 & 0x0004) == 0) {
+ int new_reg1 = mdio_read(dev, tp->phys[0], 1);
+ if ((new_reg1 & 0x0004) == 0) {
+ printk(KERN_INFO "%s: No link beat on the MII interface,"
+ " status then %4.4x now %4.4x.\n",
+ dev->name, mii_reg1, new_reg1);
+ if (tp->mtable && tp->mtable->has_nonmii)
+ goto select_next_media;
+ }
+ }
+ if (mii_reg5 == 0xffff || mii_reg5 == 0x0000)
+ ; /* No MII device or no link partner report */
+ else if (tp->full_duplex_lock)
+ ;
+ else {
+ int negotiated = mii_reg5 & tp->advertising[0];
+ int duplex = ((negotiated & 0x0100) != 0
+ || (negotiated & 0x00C0) == 0x0040);
+ /* 100baseTx-FD or 10T-FD, but not 100-HD */
+ if (tp->full_duplex != duplex) {
+ tp->full_duplex = duplex;
+ if (tp->full_duplex)
+ tp->csr6 |= 0x0200;
+ else
+ tp->csr6 &= ~0x0200;
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ if (tulip_debug > 0) /* Gurppp, should be >1 */
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII"
+ " Xcvr #%d parter capability of %4.4x.\n",
+ dev->name, tp->full_duplex ? "full" : "half",
+ tp->phys[0], mii_reg5);
+ }
+ }
+ next_tick = 60*HZ;
+ break;
+ }
+ case 2: /* 21142 serial block has no link beat. */
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ if (next_tick) {
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+ }
+}
+
+/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
+ of available transceivers. */
+static void t21142_timer(unsigned long data)
+{
+ struct device *dev = (struct device *)data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr12 = inl(ioaddr + CSR12);
+ int next_tick = 60*HZ;
+ int new_csr6 = 0;
+
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: 21142 negotiation status %8.8x, %s.\n",
+ dev->name, csr12, medianame[dev->if_port]);
+ if (dev->if_port == 3) {
+ if (csr12 & 2) { /* No 100mbps link beat, revert to 10mbps. */
+ new_csr6 = 0x82420200;
+ outl(new_csr6, ioaddr + CSR6);
+ outl(0x0000, ioaddr + CSR13);
+ outl(0x0003FFFF, ioaddr + CSR14);
+ outl(0x0008, ioaddr + CSR15);
+ outl(0x0001, ioaddr + CSR13);
+ outl(0x1301, ioaddr + CSR12); /* Start NWay. */
+ }
+ } else if ((csr12 & 0x7000) != 0x5000) {
+ /* Negotiation failed. Search media types. */
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: 21142 negotiation failed, status %8.8x.\n",
+ dev->name, csr12);
+ if (!(csr12 & 4)) { /* 10mbps link beat good. */
+ new_csr6 = 0x82420000;
+ dev->if_port = 0;
+ outl(0, ioaddr + CSR13);
+ outl(0x0003FFFF, ioaddr + CSR14);
+ outl(t21142_csr15[dev->if_port], ioaddr + CSR15);
+ outl(t21142_csr13[dev->if_port], ioaddr + CSR13);
+ } else if (csr12 & 0x100) {
+ new_csr6 = 0x82420200;
+ dev->if_port = 2;
+ outl(0, ioaddr + CSR13);
+ outl(0x0003FFFF, ioaddr + CSR14);
+ outl(0x0008, ioaddr + CSR15);
+ outl(0x0001, ioaddr + CSR13);
+ } else {
+ /* Select 100mbps port to check for link beat. */
+ new_csr6 = 0x83860000;
+ dev->if_port = 3;
+ outl(0, ioaddr + CSR13);
+ outl(0x0003FF7F, ioaddr + CSR14);
+ outl(8, ioaddr + CSR15);
+ outl(1, ioaddr + CSR13);
+ }
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: Testing new 21142 media %s.\n",
+ dev->name, medianame[dev->if_port]);
+ if (new_csr6 != (tp->csr6 & ~0x00D5)) {
+ tp->csr6 &= 0x00D5;
+ tp->csr6 |= new_csr6;
+ outl(0x0301, ioaddr + CSR12);
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ }
+ }
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+}
+
+static void t21142_lnk_change( struct device *dev)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr12 = inl(ioaddr + CSR12);
+
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: 21142 link status interrupt %8.8x, CSR5 %x.\n",
+ dev->name, csr12, inl(ioaddr + CSR5));
+
+ if ((csr12 & 0x7000) == 0x5000) {
+ if (csr12 & 0x01800000) {
+ /* Switch to 100mbps mode. */
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ if (csr12 & 0x01000000) {
+ dev->if_port = 5;
+ tp->csr6 = 0x83860200;
+ } else {
+ dev->if_port = 3;
+ tp->csr6 = 0x83860000;
+ }
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ } /* Else 10baseT-FD is handled automatically. */
+ } else if (dev->if_port == 3) {
+ if (!(csr12 & 2))
+ printk(KERN_INFO"%s: 21142 100baseTx link beat good.\n",
+ dev->name);
+ else
+ dev->if_port = 0;
+ } else if (dev->if_port == 0) {
+ if (!(csr12 & 4))
+ printk(KERN_INFO"%s: 21142 10baseT link beat good.\n",
+ dev->name);
+ } else if (!(csr12 & 4)) { /* 10mbps link beat good. */
+ printk(KERN_INFO"%s: 21142 10mpbs sensed media.\n",
+ dev->name);
+ dev->if_port = 0;
+ } else { /* 100mbps link beat good. */
+ printk(KERN_INFO"%s: 21142 100baseTx sensed media.\n",
+ dev->name);
+ dev->if_port = 3;
+ tp->csr6 = 0x83860000;
+ outl(0x0003FF7F, ioaddr + CSR14);
+ outl(0x0301, ioaddr + CSR12);
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ }
+}
+
+
+static void mxic_timer(unsigned long data)
+{
+ struct device *dev = (struct device *)data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int next_tick = 60*HZ;
+
+ if (tulip_debug > 3) {
+ printk(KERN_INFO"%s: MXIC negotiation status %8.8x.\n", dev->name,
+ inl(ioaddr + CSR12));
+ }
+ if (next_tick) {
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
+ }
+}
+
+static void pnic_timer(unsigned long data)
+{
+ struct device *dev = (struct device *)data;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ int csr12 = inl(ioaddr + CSR12);
+ int next_tick = 60*HZ;
+ int new_csr6 = tp->csr6 & ~0x40C40200;
+
+ if (media_cap[dev->if_port] & MediaIsMII) {
+ int negotiated = mdio_read(dev, tp->phys[0], 5) & tp->advertising[0];
+
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: LC82C168 negotiated capability %8.8x, "
+ "CSR5 %8.8x.\n",
+ dev->name, negotiated, inl(ioaddr + CSR5));
+
+ if (negotiated & 0x0380) /* 10 vs 100mbps */
+ new_csr6 |= 0x812E0000;
+ else
+ new_csr6 |= 0x816E0000;
+ if (((negotiated & 0x0300) == 0x0100) /* Duplex */
+ || (negotiated & 0x00C0) == 0x0040
+ || tp->full_duplex_lock) {
+ tp->full_duplex = 1;
+ new_csr6 |= 0x0200;
+ }
+ if (tulip_debug > 1)
+ printk(KERN_DEBUG "%s: LC82C168 MII PHY status %4.4x, Link "
+ "partner report %4.4x, csr6 %8.8x/%8.8x.\n",
+ dev->name, mdio_read(dev, tp->phys[0], 1), negotiated,
+ tp->csr6, inl(ioaddr + CSR6));
+ } else {
int phy_reg = inl(ioaddr + 0xB8);
+ int csr5 = inl(ioaddr + CSR5);
+
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: LC82C168 phy status %8.8x, CSR5 %8.8x.\n",
- dev->name, phy_reg, inl(ioaddr + CSR5));
+ dev->name, phy_reg, csr5);
+
if (phy_reg & 0x04000000) { /* Remote link fault */
- outl(0x0201F078, ioaddr + 0xB8);
- next_tick = (24*HZ)/10;
- } else
- next_tick = 10*HZ;
+ /*outl(0x0201F078, ioaddr + 0xB8);*/
+ next_tick = 3*HZ;
+ }
if (inl(ioaddr + CSR5) & TPLnkFail) { /* 100baseTx link beat */
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, "
"CSR5 %8.8x, PHY %3.3x.\n",
dev->name, medianame[dev->if_port], csr12,
inl(ioaddr + CSR5), inl(ioaddr + 0xB8));
- if (dev->if_port == 0) {
+ if (tp->medialock) {
+ } else if (dev->if_port == 0) {
dev->if_port = 3;
- } else
- dev->if_port = 0;
- next_tick = (24*HZ)/10;
- select_media(dev, 0);
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- dev->trans_start = jiffies;
- }
- break;
- }
- case DC21140: case DC21142: {
- struct medialeaf *mleaf;
- unsigned char *p;
- if (tp->mtable == NULL) { /* No EEPROM info, use generic code. */
- /* Assume this is like a SMC card, and check its link beat bit. */
- if ((dev->if_port == 0 && (csr12 & 0x0080)) ||
- (dev->if_port == 1 && (csr12 & 0x0040) == 0)) {
- dev->if_port ^= 1;
- /* Stop the transmit process. */
- tp->csr6 = (dev->if_port ? 0x03860000 : 0x02420000);
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- printk(KERN_INFO "%s: link beat timed out, CSR12 is 0x%2.2x, switching to"
- " %s media.\n", dev->name,
- csr12 & 0xff,
- dev->if_port ? "100baseTx" : "10baseT");
- outl(tp->csr6 | 0xA002, ioaddr + CSR6);
- dev->trans_start = jiffies;
- next_tick = (24*HZ)/10;
+ outl(0x33, ioaddr + CSR12);
+ new_csr6 = 0x01860000;
+ outl(0x1F868, ioaddr + 0xB8);
} else {
- next_tick = 10*HZ;
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: network media monitor 0x%2.2x, link"
- " beat detected as %s.\n", dev->name,
- csr12 & 0xff,
- dev->if_port ? "100baseTx" : "10baseT");
+ dev->if_port = 0;
+ outl(0x32, ioaddr + CSR12);
+ new_csr6 = 0x00420000;
+ outl(0x1F078, ioaddr + 0xB8);
}
- break;
+ new_csr6 |= (tp->csr6 & 0xfdff);
+ next_tick = 3*HZ;
+ } else
+ new_csr6 = tp->csr6;
+ if (tp->full_duplex_lock || (phy_reg & 0x30000000) != 0) {
+ tp->full_duplex = 1;
+ new_csr6 |= 0x00000200;
}
- mleaf = &tp->mtable->mleaf[tp->cur_index];
- p = mleaf->leafdata;
- switch (mleaf->type) {
- case 0: case 4: {
- /* Type 0 non-MII or #4 SYM transceiver. Check the link beat bit. */
- s8 bitnum = p[mleaf->type == 4 ? 5 : 2];
- if (tulip_debug > 2)
- printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x bit %d is"
- " %d, expecting %d.\n",
- dev->name, csr12, (bitnum >> 1) & 7,
- (csr12 & (1 << ((bitnum >> 1) & 7))) != 0,
- (bitnum >= 0));
- /* Check that the specified bit has the proper value. */
- if ((bitnum < 0) !=
- ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) {
- if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name,
- medianame[mleaf->media]);
- break;
- }
- if (tp->medialock)
- break;
- select_next_media:
- if (--tp->cur_index < 0) {
- /* We start again, but should instead look for default. */
- tp->cur_index = tp->mtable->leafcount - 1;
- }
- dev->if_port = tp->mtable->mleaf[tp->cur_index].media;
- if (media_fd[dev->if_port])
- goto select_next_media; /* Skip FD entries. */
- if (tulip_debug > 1)
- printk(KERN_DEBUG "%s: No link beat on media %s,"
- " trying transceiver type %s.\n",
- dev->name, medianame[mleaf->media & 15],
- medianame[tp->mtable->mleaf[tp->cur_index].media]);
- select_media(dev, 0);
- /* Restart the transmit process. */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- next_tick = (24*HZ)/10;
- break;
- }
- case 1: case 3: /* 21140, 21142 MII */
- {
- int mii_reg1 = mdio_read(ioaddr, tp->phys[0], 1);
- int mii_reg5 = mdio_read(ioaddr, tp->phys[0], 5);
- printk(KERN_INFO "%s: MII monitoring tick: CSR12 %2.2x, "
- "MII status %4.4x, Link partner report %4.4x.\n",
- dev->name, csr12, mii_reg1, mii_reg5);
-#ifdef notdef
- if (mii_reg1 != 0xffff && (mii_reg1 & 0x0004) == 0)
- goto select_next_media;
-#else
- if (mii_reg1 != 0xffff && (mii_reg1 & 0x0004) == 0)
- printk(KERN_INFO "%s: No link beat on the MII interface, "
- "status then %4.4x now %4.4x.\n",
- dev->name, mii_reg1,
- mdio_read(ioaddr, tp->phys[0], 1));
-#endif
- if (mii_reg5 == 0xffff || mii_reg5 == 0x0000)
- ; /* No MII device or no link partner report */
- else if (tp->full_duplex_lock)
- ;
- else if ((mii_reg5 & 0x0100) != 0
- || (mii_reg5 & 0x00C0) == 0x0040) {
- /* 100baseTx-FD or 10T-FD, but not 100-HD */
- if (tp->full_duplex == 0) {
- tp->full_duplex = 1;
- tp->csr6 |= 0x0200;
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- }
- if (tulip_debug > 0) /* Gurppp, should be >1 */
- printk(KERN_INFO "%s: Setting %s-duplex based on MII"
- " Xcvr #%d parter capability of %4.4x.\n",
- dev->name, full_duplex ? "full" : "half",
- tp->phys[0], mii_reg5);
- }
- }
- break;
- case 2: /* 21142 serial block has no link beat. */
- default:
- break;
- }
- }
- break;
- default: /* Invalid chip type. */
- break;
}
- if (next_tick) {
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ if (tp->csr6 != new_csr6) {
+ tp->csr6 = new_csr6;
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6); /* Restart Tx */
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ dev->trans_start = jiffies;
+ if (tulip_debug > 0) /* Gurppp, should be >1 */
+ printk(KERN_INFO "%s: Changing PNIC configuration to %s-duplex, "
+ "CSR6 %8.8x.\n",
+ dev->name, tp->full_duplex ? "full" : "half", new_csr6);
}
+ tp->timer.expires = RUN_AT(next_tick);
+ add_timer(&tp->timer);
}
static void tulip_tx_timeout(struct device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
- if (tp->mtable && tp->mtable->has_mii) {
- /* Do nothing -- the media monitor should handle this. */
- if (tulip_debug > 1)
- printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
- dev->name);
+ if (media_cap[dev->if_port] & MediaIsMII) {
+ /* Do nothing -- the media monitor should handle this. */
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
+ dev->name);
+ dev->trans_start = jiffies;
+ return;
} else if (tp->chip_id == DC21040) {
if (inl(ioaddr + CSR12) & 0x0002) {
printk(KERN_INFO "%s: transmit timed out, switching to %s media.\n",
@@ -1637,20 +1994,6 @@ static void tulip_tx_timeout(struct device *dev)
}
dev->trans_start = jiffies;
return;
- } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142) {
- /* Stop the transmit process. */
- outl(tp->csr6 | 0x0002, ioaddr + CSR6);
- dev->if_port ^= 1;
- printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
- "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
- dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
- inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
- printk(KERN_WARNING "%s: transmit timed out, switching to %s media.\n",
- dev->name, dev->if_port ? "100baseTx" : "10baseT");
- outl(tp->csr6 | 0x2002, ioaddr + CSR6);
- tp->stats.tx_errors++;
- dev->trans_start = jiffies;
- return;
} else if (tp->chip_id == DC21041) {
u32 csr12 = inl(ioaddr + CSR12);
@@ -1659,19 +2002,38 @@ static void tulip_tx_timeout(struct device *dev)
dev->name, inl(ioaddr + CSR5), csr12,
inl(ioaddr + CSR13), inl(ioaddr + CSR14));
tp->mediasense = 1;
-
- if (dev->if_port == 1 || dev->if_port == 2) {
+ if (dev->if_port == 1 || dev->if_port == 2)
if (csr12 & 0x0004) {
dev->if_port = 2 - dev->if_port;
} else
dev->if_port = 0;
- } else
+ else
dev->if_port = 1;
-
select_media(dev, 0);
tp->stats.tx_errors++;
dev->trans_start = jiffies;
return;
+ } else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
+ || tp->chip_id == MX98713) {
+ /* Stop the transmit process. */
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
+ "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
+ dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
+ inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
+ if (tp->mtable) {
+ if (--tp->cur_index < 0) {
+ /* We start again, but should instead look for default. */
+ tp->cur_index = tp->mtable->leafcount - 1;
+ }
+ select_media(dev, 0);
+ printk(KERN_WARNING "%s: transmit timed out, switching to %s media.\n",
+ dev->name, dev->if_port ? "100baseTx" : "10baseT");
+ }
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ tp->stats.tx_errors++;
+ dev->trans_start = jiffies;
+ return;
} else
printk(KERN_WARNING "%s: transmit timed out, status %8.8x, CSR12 %8.8x,"
" resetting...\n",
@@ -1753,40 +2115,12 @@ tulip_start_xmit(struct sk_buff *skb, struct device *dev)
int entry;
u32 flag;
-#ifdef ORIGINAL_TEXT
-#ifndef final_version
- if (skb == NULL || skb->len <= 0) {
- printk(KERN_ERR "%s: Obsolete driver layer request made: skbuff==NULL.\n",
- dev->name);
- dev_tint(dev);
- return 0;
- }
-#endif
-#endif
-
-#ifdef CONFIG_NET_FASTROUTE
- cli();
- if (xchg(&dev->tx_semaphore,0) == 0) {
- sti();
- /* With new queueing algorithm returning 1 when dev->tbusy == 0
- should not result in lockups, but I am still not sure. --ANK
- */
- if (net_ratelimit())
- printk(KERN_CRIT "Please check: are you still alive?\n");
- return 1;
- }
-#endif
/* Block a timer-based transmit from overlapping. This could better be
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-#ifdef CONFIG_NET_FASTROUTE
- sti();
-#endif
- if (jiffies - dev->trans_start >= TX_TIMEOUT)
- tulip_tx_timeout(dev);
-#ifdef CONFIG_NET_FASTROUTE
- dev->tx_semaphore = 1;
-#endif
+ if (jiffies - dev->trans_start < TX_TIMEOUT)
+ return 1;
+ tulip_tx_timeout(dev);
return 1;
}
@@ -1816,7 +2150,6 @@ tulip_start_xmit(struct sk_buff *skb, struct device *dev)
if (entry == TX_RING_SIZE-1)
flag |= 0xe2000000;
- tp->stats.tx_bytes += skb->len;
tp->tx_ring[entry].length = skb->len | flag;
tp->tx_ring[entry].status = 0x80000000; /* Pass ownership to the chip. */
tp->cur_tx++;
@@ -1824,10 +2157,6 @@ tulip_start_xmit(struct sk_buff *skb, struct device *dev)
outl(0, dev->base_addr + CSR1);
dev->trans_start = jiffies;
-#ifdef CONFIG_NET_FASTROUTE
- dev->tx_semaphore = 1;
- sti();
-#endif
return 0;
}
@@ -1842,8 +2171,9 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
struct device *dev = (struct device *)(irq2dev_map[irq]);
#endif
- struct tulip_private *lp;
- int csr5, ioaddr, boguscnt = 12;
+ struct tulip_private *tp;
+ long ioaddr;
+ int csr5, work_budget = max_interrupt_work;
if (dev == NULL) {
printk (KERN_ERR" tulip_interrupt(): irq %d for unknown device.\n",
@@ -1852,11 +2182,21 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
}
ioaddr = dev->base_addr;
- lp = (struct tulip_private *)dev->priv;
- if (dev->interrupt)
+ tp = (struct tulip_private *)dev->priv;
+ if (test_and_set_bit(0, (void*)&tp->interrupt)) {
+#ifdef SMP_CHECK
+ printk(KERN_ERR "%s: Re-entering the interrupt handler with proc %d,"
+ " proc %d already handling.\n", dev->name,
+ tp->smp_proc_id, hard_smp_processor_id());
+#else
printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
-
+#endif
+ return;
+ }
dev->interrupt = 1;
+#ifdef SMP_CHECK
+ tp->smp_proc_id = hard_smp_processor_id();
+#endif
do {
csr5 = inl(ioaddr + CSR5);
@@ -1867,23 +2207,24 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n",
dev->name, csr5, inl(dev->base_addr + CSR5));
- if ((csr5 & 0x00018000) == 0)
+ if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
break;
- if (csr5 & RxIntr)
- tulip_rx(dev);
+ if (csr5 & (RxIntr | RxNoBuf))
+ work_budget -= tulip_rx(dev);
if (csr5 & (TxNoBuf | TxDied | TxIntr)) {
- int dirty_tx;
+ unsigned int dirty_tx;
- for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+ for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0;
+ dirty_tx++) {
int entry = dirty_tx % TX_RING_SIZE;
- int status = lp->tx_ring[entry].status;
+ int status = tp->tx_ring[entry].status;
if (status < 0)
break; /* It still hasn't been Txed */
/* Check for Rx filter setup frames. */
- if (lp->tx_skbuff[entry] == NULL)
+ if (tp->tx_skbuff[entry] == NULL)
continue;
if (status & 0x8000) {
@@ -1893,74 +2234,104 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
dev->name, status);
#endif
- lp->stats.tx_errors++;
- if (status & 0x4104) lp->stats.tx_aborted_errors++;
- if (status & 0x0C00) lp->stats.tx_carrier_errors++;
- if (status & 0x0200) lp->stats.tx_window_errors++;
- if (status & 0x0002) lp->stats.tx_fifo_errors++;
- if ((status & 0x0080) && lp->full_duplex == 0)
- lp->stats.tx_heartbeat_errors++;
+ tp->stats.tx_errors++;
+ if (status & 0x4104) tp->stats.tx_aborted_errors++;
+ if (status & 0x0C00) tp->stats.tx_carrier_errors++;
+ if (status & 0x0200) tp->stats.tx_window_errors++;
+ if (status & 0x0002) tp->stats.tx_fifo_errors++;
+ if ((status & 0x0080) && tp->full_duplex == 0)
+ tp->stats.tx_heartbeat_errors++;
#ifdef ETHER_STATS
- if (status & 0x0100) lp->stats.collisions16++;
+ if (status & 0x0100) tp->stats.collisions16++;
#endif
} else {
#ifdef ETHER_STATS
- if (status & 0x0001) lp->stats.tx_deferred++;
+ if (status & 0x0001) tp->stats.tx_deferred++;
#endif
- lp->stats.collisions += (status >> 3) & 15;
- lp->stats.tx_packets++;
+#if LINUX_VERSION_CODE > 0x20127
+ tp->stats.tx_bytes += tp->tx_ring[entry].length & 0x7ff;
+#endif
+ tp->stats.collisions += (status >> 3) & 15;
+ tp->stats.tx_packets++;
}
/* Free the original skb. */
- dev_kfree_skb(lp->tx_skbuff[entry]);
- lp->tx_skbuff[entry] = 0;
+#if (LINUX_VERSION_CODE > 0x20155)
+ dev_kfree_skb(tp->tx_skbuff[entry]);
+#else
+ dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE);
+#endif
+ tp->tx_skbuff[entry] = 0;
}
#ifndef final_version
- if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+ if (tp->cur_tx - dirty_tx > TX_RING_SIZE) {
printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
- dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+ dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
dirty_tx += TX_RING_SIZE;
}
#endif
- if (lp->tx_full && dev->tbusy
- && dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+ if (tp->tx_full && dev->tbusy
+ && tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) {
/* The ring is no longer full, clear tbusy. */
- lp->tx_full = 0;
+ tp->tx_full = 0;
dev->tbusy = 0;
mark_bh(NET_BH);
}
- lp->dirty_tx = dirty_tx;
+ tp->dirty_tx = dirty_tx;
+ if (csr5 & TxDied) {
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: The transmitter stopped!"
+ " CSR5 is %x, CSR6 %x.\n",
+ dev->name, csr5, inl(ioaddr + CSR6));
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
+ }
}
/* Log errors. */
- if (csr5 & 0x8000) { /* Abnormal error summary bit. */
- if (csr5 & TxJabber) lp->stats.tx_errors++;
+ if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */
+ if (csr5 & TxJabber) tp->stats.tx_errors++;
if (csr5 & TxFIFOUnderflow) {
- lp->csr6 |= 0x00200000; /* Reconfigure to store-n-forward. */
- /* Restart the transmit process. */
- outl(lp->csr6 | 0x0002, ioaddr + CSR6);
- outl(lp->csr6 | 0x2002, ioaddr + CSR6);
+ if ((tp->csr6 & 0xC000) != 0xC000)
+ tp->csr6 += 0x4000; /* Bump up the Tx threshold */
+ else
+ tp->csr6 |= 0x00200000; /* Store-n-forward. */
+ /* Restart the transmit process. */
+ outl(tp->csr6 | 0x0002, ioaddr + CSR6);
+ outl(tp->csr6 | 0x2002, ioaddr + CSR6);
}
if (csr5 & RxDied) { /* Missed a Rx frame. */
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
+ tp->stats.rx_errors++;
+ tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
}
if (csr5 & TimerInt) {
printk(KERN_ERR "%s: Something Wicked happened! %8.8x.\n",
dev->name, csr5);
/* Hmmmmm, it's not clear what to do here. */
}
+ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)
+ && tp->chip_id == DC21142) {
+ if (tulip_debug > 1)
+ printk(KERN_INFO"%s: 21142 link change, CSR5 = %8.8x.\n",
+ dev->name, csr5);
+ t21142_lnk_change(dev);
+ }
/* Clear all error sources, included undocumented ones! */
- outl(0x000f7ba, ioaddr + CSR5);
+ outl(0x0800f7ba, ioaddr + CSR5);
}
- if (--boguscnt < 0) {
- printk(KERN_WARNING "%s: Too much work at interrupt, csr5=0x%8.8x.\n",
- dev->name, csr5);
- /* Clear all interrupt sources. */
- outl(0x0001ffff, ioaddr + CSR5);
+ if (--work_budget < 0) {
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: Too much work at interrupt, "
+ "csr5=0x%8.8x.\n", dev->name, csr5);
+ /* Acknowledge all interrupt sources. */
+ outl(0x8001ffff, ioaddr + CSR5);
+#ifdef notdef
+ /* Clear all but standard interrupt sources. */
+ outl((~csr5) & 0x0001ebef, ioaddr + CSR7);
+#endif
break;
}
} while (1);
@@ -1969,271 +2340,82 @@ static void tulip_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *reg
printk(KERN_DEBUG "%s: exiting interrupt, csr5=%#4.4x.\n",
dev->name, inl(ioaddr + CSR5));
- /* Code that should never be run! Perhaps remove after testing.. */
- {
- static int stopit = 10;
- if (dev->start == 0 && --stopit < 0) {
- printk(KERN_ERR "%s: Emergency stop, looping startup interrupt.\n"
- KERN_ERR "%s: Disabling interrupt handler %d to avoid "
- "locking up the machine.\n",
- dev->name, dev->name, dev->irq);
-#ifdef SA_SHIRQ
- free_irq(irq, dev);
-#else
- free_irq(irq);
-#endif
- }
- }
-
dev->interrupt = 0;
+ clear_bit(0, (void*)&tp->interrupt);
return;
}
-#ifdef CONFIG_NET_FASTROUTE
-/* DMAing cards are the most easy in this respect,
- they are able to make fast route to any device.
-
- Now we allow to make it only to another ethernet card.
- */
-static int tulip_accept_fastpath(struct device *dev, struct dst_entry *dst)
-{
- struct device *odev = dst->dev;
-
- if (dst->ops->protocol != __constant_htons(ETH_P_IP))
- return -1;
- if (odev->type != ARPHRD_ETHER || odev->accept_fastpath == NULL)
- return -1;
-
- return 0;
-}
-
-/*
- Return values:
-
- 0 - packet has gone by fast path.
- 1 - fast path is OK, but device deferred xmit. (semifast path)
-
- 2 - fast path is hit, but packet is a bit strange. (NI)
- 3 - oom
-
- 4 - fast path miss.
- */
-
-static int tulip_fast_forward(struct device *dev, int entry, int len)
-{
- struct tulip_private *lp = (struct tulip_private *)dev->priv;
- struct sk_buff *skb = lp->rx_skbuff[entry];
- struct ethhdr *eth = (void*)skb->data;
-
- if (eth->h_proto == __constant_htons(ETH_P_IP)) {
- struct rtable *rt;
- struct iphdr *iph;
- unsigned h;
-
- iph = (struct iphdr*)(skb->data + ETH_HLEN);
- h = (*(u8*)&iph->daddr^*(u8*)&iph->saddr)&NETDEV_FASTROUTE_HMASK;
- rt = (struct rtable*)(dev->fastpath[h]);
- if (rt &&
- ((u16*)&iph->daddr)[0] == ((u16*)&rt->key.dst)[0] &&
- ((u16*)&iph->daddr)[1] == ((u16*)&rt->key.dst)[1] &&
- ((u16*)&iph->saddr)[0] == ((u16*)&rt->key.src)[0] &&
- ((u16*)&iph->saddr)[1] == ((u16*)&rt->key.src)[1] &&
- rt->u.dst.obsolete == 0) {
- struct device *odev = rt->u.dst.dev;
-
- dev_fastroute_stat.hits++;
-
- if (*(u8*)iph != 0x45 ||
- (eth->h_dest[0]&1) ||
- !neigh_is_valid(rt->u.dst.neighbour) ||
- iph->ttl <= 1)
- goto alas2;
-
- ip_decrease_ttl(iph);
-
- if (1) {
- struct sk_buff *skb2 = DEV_ALLOC_SKB(PKT_BUF_SZ);
- if (skb2 == NULL)
- goto oom;
- lp->rx_ring[entry].buffer1 = virt_to_bus(skb2->tail);
- skb2->dev = dev;
- lp->rx_skbuff[entry] = skb2;
- }
-
- skb_put(skb, len);
-
- ip_statistics.IpInReceives++;
- ip_statistics.IpForwDatagrams++;
-
- /* Could use hh cache */
- memcpy(eth->h_source, odev->dev_addr, 6);
- memcpy(eth->h_dest, rt->u.dst.neighbour->ha, 6);
- skb->dev = odev;
-
-#ifdef FAST_SKB_RECYCLE /* DO NOT DEFINE IT! READ COMMENT */
- /* We could use fast buffer recycling here if odev
- is not DMAing.
-
- The only problem is that we must allocate skb2
- BEFORE we lose skb, otherwise we would make hole in
- tulip rx array. Hence, to implement FAST_SKB_RECYCLE
- we need always keep at least one skb in a safe place.
- */
- atomic_inc(&skb->users);
-#endif
-
- if (odev->tx_semaphore &&
- odev->tbusy == 0 &&
- odev->interrupt == 0 &&
- odev->hard_start_xmit(skb, odev) == 0) {
-#ifdef FAST_SKB_RECYCLE
- if (atomic_read(&skb->users) == 1) {
- skb->tail = skb->data;
- skb->len = 0;
- }
-#endif
- dev_fastroute_stat.succeed++;
- return 0;
- }
-#ifdef FAST_SKB_RECYCLE
- atomic_dec(&skb->users);
-#endif
-
- /* Otherwise... */
- skb->pkt_type = PACKET_FASTROUTE;
- skb->nh.raw = skb->data + ETH_HLEN;
- skb->protocol = __constant_htons(ETH_P_IP);
- dev_fastroute_stat.deferred++;
- return 1;
- }
- }
- return 4;
-
-oom:
- return 3;
-
-alas2:
-#ifdef not_yet
- skb->dst = dst_clone(&rt->u.dst);
- return 2;
-#else
- return 4;
-#endif
-}
-#endif
-
static int
tulip_rx(struct device *dev)
{
- struct tulip_private *lp = (struct tulip_private *)dev->priv;
- int entry = lp->cur_rx % RX_RING_SIZE;
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ int entry = tp->cur_rx % RX_RING_SIZE;
+ int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+ int work_done = 0;
if (tulip_debug > 4)
printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry,
- lp->rx_ring[entry].status);
+ tp->rx_ring[entry].status);
/* If we own the next entry, it's a new packet. Send it up. */
- while (lp->rx_ring[entry].status >= 0) {
- int status = lp->rx_ring[entry].status;
+ while (tp->rx_ring[entry].status >= 0) {
+ s32 status = tp->rx_ring[entry].status;
+ if (--rx_work_limit < 0)
+ break;
if ((status & 0x0300) != 0x0300) {
if ((status & 0xffff) != 0x7fff) { /* Ingore earlier buffers. */
- printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
- "multiple buffers, status %8.8x!\n", dev->name, status);
- lp->stats.rx_length_errors++;
+ if (tulip_debug > 1)
+ printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
+ "multiple buffers, status %8.8x!\n",
+ dev->name, status);
+ tp->stats.rx_length_errors++;
}
} else if (status & 0x8000) {
/* There was a fatal error. */
- lp->stats.rx_errors++; /* end of a packet.*/
- if (status & 0x0890) lp->stats.rx_length_errors++;
- if (status & 0x0004) lp->stats.rx_frame_errors++;
- if (status & 0x0002) lp->stats.rx_crc_errors++;
- if (status & 0x0001) lp->stats.rx_fifo_errors++;
+ if (tulip_debug > 2)
+ printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
+ dev->name, status);
+ tp->stats.rx_errors++; /* end of a packet.*/
+ if (status & 0x0890) tp->stats.rx_length_errors++;
+ if (status & 0x0004) tp->stats.rx_frame_errors++;
+ if (status & 0x0002) tp->stats.rx_crc_errors++;
+ if (status & 0x0001) tp->stats.rx_fifo_errors++;
} else {
- /* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
- short pkt_len = (lp->rx_ring[entry].status >> 16) - 4;
+ short pkt_len = (status >> 16) - 4;
struct sk_buff *skb;
- int rx_in_place = 0;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (netdev_dropping)
- goto throttle;
-#endif
-
- skb = lp->rx_skbuff[entry];
-
-#ifdef CONFIG_NET_FASTROUTE
- switch (tulip_fast_forward(dev, entry, pkt_len)) {
- case 0:
- goto gone;
- case 1:
- goto semi_gone;
- case 2:
- break;
- case 3:
- skb = NULL;
- goto memory_squeeze;
- }
-#endif
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
- if (pkt_len > rx_copybreak) {
- struct sk_buff *newskb;
- char *temp;
-
- /* Get a fresh skbuff to replace the filled one. */
- newskb = DEV_ALLOC_SKB(PKT_BUF_SZ);
- if (newskb == NULL) {
- skb = NULL; /* No memory, drop the packet. */
- goto memory_squeeze;
- }
- /* Pass up the skb already on the Rx ring. */
- temp = skb_put(skb, pkt_len);
- if (bus_to_virt(lp->rx_ring[entry].buffer1) != temp)
- printk(KERN_ERR "%s: Internal consistency error -- the "
- "skbuff addresses do not match"
- " in tulip_rx: %p vs. %p / %p.\n", dev->name,
- bus_to_virt(lp->rx_ring[entry].buffer1),
- skb->head, temp);
- rx_in_place = 1;
- lp->rx_skbuff[entry] = newskb;
- newskb->dev = dev;
- /* Longword alignment required: do not skb_reserve(2)! */
- lp->rx_ring[entry].buffer1 = virt_to_bus(newskb->tail);
- } else
- skb = DEV_ALLOC_SKB(pkt_len + 2);
-memory_squeeze:
- if (skb == NULL) {
- int i;
- printk(KERN_WARNING "%s: Memory squeeze, deferring packet.\n",
- dev->name);
- /* Check that at least two ring entries are free.
- If not, free one and mark stats->rx_dropped++. */
- for (i = 0; i < RX_RING_SIZE; i++)
- if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0)
- break;
-
- if (i > RX_RING_SIZE -2) {
- lp->stats.rx_dropped++;
- lp->rx_ring[entry].status = 0x80000000;
- lp->cur_rx++;
- }
- break;
- }
- skb->dev = dev;
- if (! rx_in_place) {
- skb_reserve(skb, 2); /* 16 byte align the data fields */
-#if LINUX_VERSION_CODE < 0x20200 || defined(__alpha__)
+ if (pkt_len < rx_copybreak
+ && (skb = DEV_ALLOC_SKB(pkt_len+2)) != NULL) {
+ skb->dev = dev;
+ skb_reserve(skb, 2); /* 16 byte align the IP header */
+#if LINUX_VERSION_CODE < 0x10300
+ memcpy(skb->data, tp->rx_ring[entry].buffer1, pkt_len);
+#elif LINUX_VERSION_CODE < 0x20200 || defined(__alpha__)
memcpy(skb_put(skb, pkt_len),
- bus_to_virt(lp->rx_ring[entry].buffer1), pkt_len);
-#else
-#ifdef ORIGINAL_TEXT
-#warning Code untested
+ bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
#else
-#error Code is wrong, and it has nothing to do with 2.2 :-)
+ eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
+ pkt_len, 0);
+ skb_put(skb, pkt_len);
#endif
- eth_copy_and_sum(skb, bus_to_virt(lp->rx_ring[entry].buffer1),
- pkt_len, 0);
+ work_done++;
+ } else { /* Pass up the skb already on the Rx ring. */
+ skb = tp->rx_skbuff[entry];
+ tp->rx_skbuff[entry] = NULL;
+#ifndef final_version
+ {
+ void *temp = skb_put(skb, pkt_len);
+ if (bus_to_virt(tp->rx_ring[entry].buffer1) != temp)
+ printk(KERN_ERR "%s: Internal consistency error! The "
+ "skbuff addresses do not match in tulip_rx:"
+ " %p vs. %p / %p.\n", dev->name,
+ bus_to_virt(tp->rx_ring[entry].buffer1),
+ skb->head, temp);
+ }
+#else
skb_put(skb, pkt_len);
#endif
}
@@ -2242,56 +2424,48 @@ memory_squeeze:
#else
skb->len = pkt_len;
#endif
-#ifdef CONFIG_NET_FASTROUTE
-semi_gone:
-#endif
netif_rx(skb);
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (netdev_dropping) {
-throttle:
- if (lp->fc_bit) {
- outl(lp->csr6 | 0x2000, dev->base_addr + CSR6);
- set_bit(lp->fc_bit, &netdev_fc_xoff);
- }
- }
-#endif
-#ifdef CONFIG_NET_FASTROUTE
-gone:
-#endif
- lp->stats.rx_packets++;
-#ifndef ORIGINAL_TEXT
- lp->stats.rx_bytes += pkt_len;
+ dev->last_rx = jiffies;
+ tp->stats.rx_packets++;
+#if LINUX_VERSION_CODE > 0x20127
+ tp->stats.rx_bytes += pkt_len;
#endif
}
+ entry = (++tp->cur_rx) % RX_RING_SIZE;
+ }
- lp->rx_ring[entry].status = 0x80000000;
- entry = (++lp->cur_rx) % RX_RING_SIZE;
+ /* Refill the Rx ring buffers. */
+ for (; tp->cur_rx - tp->dirty_rx > 0; tp->dirty_rx++) {
+ entry = tp->dirty_rx % RX_RING_SIZE;
+ if (tp->rx_skbuff[entry] == NULL) {
+ struct sk_buff *skb;
+ skb = tp->rx_skbuff[entry] = DEV_ALLOC_SKB(PKT_BUF_SZ);
+ if (skb == NULL)
+ break;
+ skb->dev = dev; /* Mark as being used by this device. */
+#if LINUX_VERSION_CODE > 0x10300
+ tp->rx_ring[entry].buffer1 = virt_to_bus(skb->tail);
+#else
+ tp->rx_ring[entry].buffer1 = virt_to_bus(skb->data);
+#endif
+ work_done++;
+ }
+ tp->rx_ring[entry].status = 0x80000000;
}
- return 0;
+ return work_done;
}
static int
tulip_close(struct device *dev)
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
int i;
-#ifdef CONFIG_NET_FASTROUTE
- dev->tx_semaphore = 0;
-#endif
dev->start = 0;
dev->tbusy = 1;
-#ifdef CONFIG_NET_HW_FLOWCONTROL
- if (tp->fc_bit) {
- int bit = tp->fc_bit;
- tp->fc_bit = 0;
- netdev_unregister_fc(bit);
- }
-#endif
-
if (tulip_debug > 1)
printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
dev->name, inl(ioaddr + CSR5));
@@ -2326,12 +2500,20 @@ tulip_close(struct device *dev)
#if LINUX_VERSION_CODE < 0x20100
skb->free = 1;
#endif
+#if (LINUX_VERSION_CODE > 0x20155)
dev_kfree_skb(skb);
+#else
+ dev_kfree_skb(skb, FREE_WRITE);
+#endif
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
if (tp->tx_skbuff[i])
+#if (LINUX_VERSION_CODE > 0x20155)
dev_kfree_skb(tp->tx_skbuff[i]);
+#else
+ dev_kfree_skb(tp->tx_skbuff[i], FREE_WRITE);
+#endif
tp->tx_skbuff[i] = 0;
}
@@ -2345,7 +2527,7 @@ static struct enet_statistics *
tulip_get_stats(struct device *dev)
{
struct tulip_private *tp = (struct tulip_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
if (dev->start)
tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
@@ -2353,6 +2535,71 @@ tulip_get_stats(struct device *dev)
return &tp->stats;
}
+#ifdef HAVE_PRIVATE_IOCTL
+/* Provide ioctl() calls to examine the MII xcvr state. */
+static int private_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+ struct tulip_private *tp = (struct tulip_private *)dev->priv;
+ long ioaddr = dev->base_addr;
+ u16 *data = (u16 *)&rq->ifr_data;
+ int phy = tp->phys[0] & 0x1f;
+ long flags;
+
+ switch(cmd) {
+ case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
+ if (tp->mtable && tp->mtable->has_mii)
+ data[0] = phy;
+ else if (tp->chip_id == DC21142)
+ data[0] = 32;
+ else
+ return -ENODEV;
+ return 0;
+ case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
+ if (data[0] == 32) { /* 21142 pseudo-MII */
+ int csr12 = inl(ioaddr + CSR12);
+ int csr14 = inl(ioaddr + CSR14);
+ switch (data[1]) {
+ case 0: {
+ data[3] = ((csr14<<13)&0x4000) + ((csr14<<5)&0x1000);
+ break; }
+ case 1:
+ data[3] = 0x7848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0)
+ + (csr12&0x06 ? 0x04 : 0);
+ break;
+ case 4: {
+ int csr14 = inl(ioaddr + CSR14);
+ data[3] = ((csr14>>9)&0x0380) + ((csr14>>1)&0x20) + 1;
+ break;
+ }
+ case 5: data[3] = inl(ioaddr + CSR12) >> 16; break;
+ default: data[3] = 0; break;
+ }
+ } else {
+ save_flags(flags);
+ cli();
+ data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+ restore_flags(flags);
+ }
+ return 0;
+ case SIOCDEVPRIVATE+2: /* Write the specified MII register */
+ if (!suser())
+ return -EPERM;
+ if (data[0] == 32) { /* 21142 pseudo-MII */
+ } else {
+ save_flags(flags);
+ cli();
+ mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+ restore_flags(flags);
+ }
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return -EOPNOTSUPP;
+}
+#endif /* HAVE_PRIVATE_IOCTL */
+
/* Set or clear the multicast filter for this adaptor.
Note that we only use exclusion around actually queueing the
new frame, not around filling tp->setup_frame. This is non-deterministic
@@ -2380,12 +2627,12 @@ static inline unsigned ether_crc_le(int length, unsigned char *data)
}
#ifdef NEW_MULTICAST
-static void set_multicast_list(struct device *dev)
+static void set_rx_mode(struct device *dev)
#else
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs)
#endif
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -2442,9 +2689,9 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
}
eaddrs = (u16 *)dev->dev_addr;
do {
- *setup_frm++ = eaddrs[0];
- *setup_frm++ = eaddrs[1];
- *setup_frm++ = eaddrs[2];
+ *setup_frm++ = eaddrs[0];
+ *setup_frm++ = eaddrs[1];
+ *setup_frm++ = eaddrs[2];
} while (++i < 15);
/* Now add this frame to the Tx list. */
if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
@@ -2457,19 +2704,19 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
entry = tp->cur_tx++ % TX_RING_SIZE;
if (entry != 0) {
- /* Avoid a chip errata by prefixing a dummy entry. */
- tp->tx_skbuff[entry] = 0;
- tp->tx_ring[entry].length =
- (entry == TX_RING_SIZE-1) ? 0x02000000 : 0;
- tp->tx_ring[entry].buffer1 = 0;
- tp->tx_ring[entry].status = 0x80000000;
- entry = tp->cur_tx++ % TX_RING_SIZE;
+ /* Avoid a chip errata by prefixing a dummy entry. */
+ tp->tx_skbuff[entry] = 0;
+ tp->tx_ring[entry].length =
+ (entry == TX_RING_SIZE-1) ? 0x02000000 : 0;
+ tp->tx_ring[entry].buffer1 = 0;
+ tp->tx_ring[entry].status = 0x80000000;
+ entry = tp->cur_tx++ % TX_RING_SIZE;
}
tp->tx_skbuff[entry] = 0;
/* Put the setup frame on the Tx list. */
if (entry == TX_RING_SIZE-1)
- tx_flags |= 0x02000000; /* Wrap ring. */
+ tx_flags |= 0x02000000; /* Wrap ring. */
tp->tx_ring[entry].length = tx_flags;
tp->tx_ring[entry].buffer1 = virt_to_bus(tp->setup_frame);
tp->tx_ring[entry].status = 0x80000000;
@@ -2485,15 +2732,69 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
}
}
+#ifdef CARDBUS
+
+#include <pcmcia/driver_ops.h>
+
+static dev_node_t *tulip_attach(dev_locator_t *loc)
+{
+ u16 dev_id;
+ u32 io;
+ u8 bus, devfn;
+ struct device *dev;
+
+ if (loc->bus != LOC_PCI) return NULL;
+ bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+ printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn);
+ pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
+ pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ io &= ~3;
+ dev = tulip_probe1(bus, devfn, NULL, DC21142, -1);
+ if (dev) {
+ dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+ strcpy(node->dev_name, dev->name);
+ node->major = node->minor = 0;
+ node->next = NULL;
+ MOD_INC_USE_COUNT;
+ return node;
+ }
+ return NULL;
+}
+
+static void tulip_detach(dev_node_t *node)
+{
+ struct device **devp, **next;
+ printk(KERN_INFO "tulip_detach(%s)\n", node->dev_name);
+ for (devp = &root_tulip_dev; *devp; devp = next) {
+ next = &((struct tulip_private *)(*devp)->priv)->next_module;
+ if (strcmp((*devp)->name, node->dev_name) == 0) break;
+ }
+ if (*devp) {
+ unregister_netdev(*devp);
+ kfree(*devp);
+ *devp = *next;
+ kfree(node);
+ MOD_DEC_USE_COUNT;
+ }
+}
+
+struct driver_operations tulip_ops = {
+ "tulip_cb", tulip_attach, NULL, NULL, tulip_detach
+};
+
+#endif /* Cardbus support */
+
+
#ifdef MODULE
#if LINUX_VERSION_CODE > 0x20118
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
MODULE_PARM(debug, "i");
+MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(reverse_probe, "i");
MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
#endif
/* An additional parameter that may be passed in... */
@@ -2505,8 +2806,12 @@ init_module(void)
if (debug >= 0)
tulip_debug = debug;
- root_tulip_dev = NULL;
+#ifdef CARDBUS
+ register_driver(&tulip_ops);
+ return 0;
+#else
return tulip_probe(NULL);
+#endif
}
void
@@ -2514,6 +2819,10 @@ cleanup_module(void)
{
struct device *next_dev;
+#ifdef CARDBUS
+ unregister_driver(&tulip_ops);
+#endif
+
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_tulip_dev) {
next_dev = ((struct tulip_private *)root_tulip_dev->priv)->next_module;
@@ -2528,7 +2837,8 @@ cleanup_module(void)
/*
* Local variables:
- * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c"
+ * SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c tulip.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index fead49fcb..19a937c41 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -64,19 +64,9 @@ static const int multicast_filter_limit = 32;
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
+#include <linux/version.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/errno.h>
@@ -115,7 +105,6 @@ static const int multicast_filter_limit = 32;
#define RUN_AT(x) (jiffies + (x))
#if (LINUX_VERSION_CODE >= 0x20100)
-char kernel_version[] = UTS_RELEASE;
#else
#ifndef __alpha__
#define ioremap vremap
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 52cc5815a..99d2318d0 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -508,7 +508,6 @@ cleanup_module(void)
int ioaddr = dev->base_addr - WD_NIC_OFFSET;
free_irq(dev->irq, dev);
release_region(ioaddr, WD_IO_EXTENT);
- dev->priv = NULL;
unregister_netdev(dev);
kfree(priv);
unlock_8390_module();
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 3411fd189..410121e2e 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -63,17 +63,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT ((2000*HZ)/1000)
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
#include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
@@ -93,13 +83,10 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
#include <linux/skbuff.h>
/* Kernel compatibility defines, most common to the PCCard package. */
-#include <linux/version.h> /* Evil, but neccessary */
+#include <linux/version.h> /* Evil and unneccessary */
#define RUN_AT(x) (jiffies + (x))
-#if (LINUX_VERSION_CODE >= 0x20100)
-char kernel_version[] = UTS_RELEASE;
-#endif
#if (LINUX_VERSION_CODE < 0x20123)
#define test_and_set_bit(val, addr) set_bit(val, addr)
#endif
@@ -214,7 +201,7 @@ See Packet Engines confidential appendix (prototype chips only).
static void yellowfin_timer(unsigned long data);
enum capability_flags {HasMII=1, FullTxStatus=2};
-struct chip_info {
+static struct chip_info {
u16 vendor_id, device_id, device_id_mask, pci_flags;
const char *name;
void (*media_timer)(unsigned long data);
diff --git a/drivers/net/z85230.c b/drivers/net/z85230.c
index 26cf57793..7e7cc5d14 100644
--- a/drivers/net/z85230.c
+++ b/drivers/net/z85230.c
@@ -227,7 +227,7 @@ static void z8530_rtsdtr(struct z8530_channel *c, int set)
* Receive handler. This is much like the async one but not quite the
* same or as complex
*
- * Note: Its intended that this handler can easily be seperated from
+ * Note: Its intended that this handler can easily be separated from
* the main code to run realtime. That'll be needed for some machines
* (eg to ever clock 64kbits on a sparc ;)).
*
@@ -605,7 +605,7 @@ static char reg_init[16]=
int z8530_sync_open(struct device *dev, struct z8530_channel *c)
{
c->sync = 1;
- c->mtu = dev->mtu;
+ c->mtu = dev->mtu+64;
c->count = 0;
c->skb = NULL;
c->skb2 = NULL;
@@ -641,7 +641,7 @@ int z8530_sync_dma_open(struct device *dev, struct z8530_channel *c)
unsigned long flags;
c->sync = 1;
- c->mtu = dev->mtu;
+ c->mtu = dev->mtu+64;
c->count = 0;
c->skb = NULL;
c->skb2 = NULL;
@@ -822,7 +822,7 @@ int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c)
{
printk("Opening sync interface for TX-DMA\n");
c->sync = 1;
- c->mtu = dev->mtu;
+ c->mtu = dev->mtu+64;
c->count = 0;
c->skb = NULL;
c->skb2 = NULL;
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index 2dff6d16b..0884cb0d8 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -207,11 +207,11 @@ __initfunc(int znet_probe(struct device *dev))
char *p;
/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
- for(p = (char *)0xf0000; p < (char *)0x100000; p++)
+ for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++)
if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0)
break;
- if (p >= (char *)0x100000) {
+ if (p >= (char *)phys_to_virt(0x100000)) {
if (znet_debug > 1)
printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
return ENODEV;
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index 38d8f4f6d..6658b83fd 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -632,7 +632,9 @@ void nubus_init(void)
nubus_init_via();
printk("Scanning nubus slots.\n");
nubus_probe_bus();
+#ifdef CONFIG_PROC_FS
proc_register(&proc_root, &proc_nubus);
+#endif
}
diff --git a/drivers/pci/oldproc.c b/drivers/pci/oldproc.c
index 5134a129f..4d17639d9 100644
--- a/drivers/pci/oldproc.c
+++ b/drivers/pci/oldproc.c
@@ -139,7 +139,11 @@ struct pci_dev_info dev_info[] = {
DEVICE( MATROX, MATROX_MYS, "Mystique"),
DEVICE( MATROX, MATROX_MIL_2, "Millennium II"),
DEVICE( MATROX, MATROX_MIL_2_AGP,"Millennium II AGP"),
+ DEVICE( MATROX, MATROX_G200_PCI,"Matrox G200 PCI"),
+ DEVICE( MATROX, MATROX_G200_AGP,"Matrox G200 AGP"),
DEVICE( MATROX, MATROX_MGA_IMP, "MGA Impression"),
+ DEVICE( MATROX, MATROX_G100_MM, "Matrox G100 multi monitor"),
+ DEVICE( MATROX, MATROX_G100_AGP,"Matrox G100 AGP"),
DEVICE( CT, CT_65545, "65545"),
DEVICE( CT, CT_65548, "65548"),
DEVICE( CT, CT_65550, "65550"),
@@ -158,8 +162,8 @@ struct pci_dev_info dev_info[] = {
DEVICE( SI, SI_496, "85C496"),
DEVICE( SI, SI_601, "85C601"),
DEVICE( SI, SI_5107, "5107"),
- DEVICE( SI, SI_5511, "85C5511"),
- DEVICE( SI, SI_5513, "85C5513"),
+ DEVICE( SI, SI_5511, "85C5511"),
+ DEVICE( SI, SI_5513, "85C5513"),
DEVICE( SI, SI_5571, "5571"),
DEVICE( SI, SI_5591, "5591/5592 Host"),
DEVICE( SI, SI_5597, "5597/5598 Host"),
@@ -249,6 +253,8 @@ struct pci_dev_info dev_info[] = {
DEVICE( VISION, VISION_QD8580, "QD-8580"),
DEVICE( BROOKTREE, BROOKTREE_848, "Bt848"),
DEVICE( BROOKTREE, BROOKTREE_849A, "Bt849"),
+ DEVICE( BROOKTREE, BROOKTREE_878_1,"Bt878 2nd Contr. (?)"),
+ DEVICE( BROOKTREE, BROOKTREE_878, "Bt878"),
DEVICE( BROOKTREE, BROOKTREE_8474, "Bt8474"),
DEVICE( SIERRA, SIERRA_STB, "STB Horizon 64"),
DEVICE( ACC, ACC_2056, "2056"),
@@ -325,6 +331,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( VIA, VIA_82C586_0, "VT 82C586 Apollo ISA"),
DEVICE( VIA, VIA_82C595, "VT 82C595 Apollo VP2"),
DEVICE( VIA, VIA_82C597_0, "VT 82C597 Apollo VP3"),
+ DEVICE( VIA, VIA_82C598_0, "VT 82C598 Apollo MVP3"),
DEVICE( VIA, VIA_82C926, "VT 82C926 Amazon"),
DEVICE( VIA, VIA_82C416, "VT 82C416MV"),
DEVICE( VIA, VIA_82C595_97, "VT 82C595 Apollo VP2/97"),
@@ -332,6 +339,8 @@ struct pci_dev_info dev_info[] = {
DEVICE( VIA, VIA_82C586_3, "VT 82C586B Apollo ACPI"),
DEVICE( VIA, VIA_86C100A, "VT 86C100A"),
DEVICE( VIA, VIA_82C597_1, "VT 82C597 Apollo VP3 AGP"),
+ DEVICE( VIA, VIA_82C598_1, "VT 82C598 Apollo MVP3 AGP"),
+ DEVICE( SMC2, SMC2_1211TX, "1211 TX"),
DEVICE( VORTEX, VORTEX_GDT60x0, "GDT 60x0"),
DEVICE( VORTEX, VORTEX_GDT6000B,"GDT 6000b"),
DEVICE( VORTEX, VORTEX_GDT6x10, "GDT 6110/6510"),
@@ -364,9 +373,9 @@ struct pci_dev_info dev_info[] = {
DEVICE( VORTEX, VORTEX_GDT6557RP2,"GDT 6557RP2"),
DEVICE( VORTEX, VORTEX_GDT6x11RP2,"GDT 6111RP2/6511RP2"),
DEVICE( VORTEX, VORTEX_GDT6x21RP2,"GDT 6121RP2/6521RP2"),
- DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"),
- DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"),
- DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"),
+ DEVICE( EF, EF_ATM_FPGA, "155P-MF1 (FPGA)"),
+ DEVICE( EF, EF_ATM_ASIC, "155P-MF1 (ASIC)"),
+ DEVICE( FORE, FORE_PCA200PC, "PCA-200PC"),
DEVICE( FORE, FORE_PCA200E, "PCA-200E"),
DEVICE( IMAGINGTECH, IMAGINGTECH_ICPCI, "MVC IC-PCI"),
DEVICE( PHILIPS, PHILIPS_SAA7145,"SAA7145"),
@@ -428,6 +437,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( O2, O2_6832, "6832"),
DEVICE( 3DFX, 3DFX_VOODOO, "Voodoo"),
DEVICE( 3DFX, 3DFX_VOODOO2, "Voodoo2"),
+ DEVICE( 3DFX, 3DFX_BANSHEE, "Banshee"),
DEVICE( SIGMADES, SIGMADES_6425, "REALmagic64/GX"),
DEVICE( STALLION, STALLION_ECHPCI832,"EasyConnection 8/32"),
DEVICE( STALLION, STALLION_ECHPCI864,"EasyConnection 8/64"),
@@ -441,7 +451,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( SATSAGEM, SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"),
DEVICE( HUGHES, HUGHES_DIRECPC, "DirecPC"),
DEVICE( ENSONIQ, ENSONIQ_AUDIOPCI,"AudioPCI"),
- DEVICE( ALTEON, ALTEON_ACENIC,"AceNIC"),
+ DEVICE( ALTEON, ALTEON_ACENIC, "AceNIC"),
DEVICE( PICTUREL, PICTUREL_PCIVST,"PCIVST"),
DEVICE( NVIDIA_SGS, NVIDIA_SGS_RIVA128, "Riva 128"),
DEVICE( CBOARDS, CBOARDS_DAS1602_16,"DAS1602/16"),
@@ -461,7 +471,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( S3, S3_AURORA64VP, "Aurora64V+"),
DEVICE( S3, S3_TRIO64UVP, "Trio64UV+"),
DEVICE( S3, S3_ViRGE_VX, "ViRGE/VX"),
- DEVICE( S3, S3_868, "Vision 868"),
+ DEVICE( S3, S3_868, "Vision 868"),
DEVICE( S3, S3_928, "Vision 928-P"),
DEVICE( S3, S3_864_1, "Vision 864-P"),
DEVICE( S3, S3_864_2, "Vision 864-P"),
@@ -476,6 +486,7 @@ struct pci_dev_info dev_info[] = {
DEVICE( S3, S3_ViRGE_MXP, "ViRGE/MX+"),
DEVICE( S3, S3_ViRGE_MXPMV, "ViRGE/MX+MV"),
DEVICE( S3, S3_SONICVIBES, "SonicVibes"),
+ DEVICE( DCI, DCI_PCCOM4, "PC COM PCI Bus 4 port serial Adapter"),
DEVICE( GENROCO, GENROCO_HFP832, "TURBOstor HFP832"),
DEVICE( INTEL, INTEL_82375, "82375EB"),
DEVICE( INTEL, INTEL_82424, "82424ZX Saturn"),
@@ -532,8 +543,10 @@ struct pci_dev_info dev_info[] = {
DEVICE( ADAPTEC, ADAPTEC_7884, "AIC-7884U"),
DEVICE( ADAPTEC, ADAPTEC_1030, "ABA-1030 DVB receiver"),
DEVICE( ADAPTEC2, ADAPTEC2_2940U2,"AHA-2940U2"),
+ DEVICE( ADAPTEC2, ADAPTEC2_78902, "AIC-7890/1"),
DEVICE( ADAPTEC2, ADAPTEC2_7890, "AIC-7890/1"),
DEVICE( ADAPTEC2, ADAPTEC2_3940U2,"AHA-3940U2"),
+ DEVICE( ADAPTEC2, ADAPTEC2_3950U2D,"AHA-3950U2D"),
DEVICE( ADAPTEC2, ADAPTEC2_7896, "AIC-7896/7"),
DEVICE( ATRONICS, ATRONICS_2015, "IDE-2015PL"),
DEVICE( TIGERJET, TIGERJET_300, "Tiger300 ISDN"),
@@ -575,7 +588,7 @@ static struct pci_dev_info *pci_lookup_dev(unsigned int vendor, unsigned int dev
return 0;
continue;
}
-
+
return & dev_info[ i ];
}
}
@@ -734,6 +747,7 @@ static const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_INIT: return "Initio Corp";
case PCI_VENDOR_ID_TTI: return "Triones Technologies, Inc.";
case PCI_VENDOR_ID_VIA: return "VIA Technologies";
+ case PCI_VENDOR_ID_SMC2: return "SMC";
case PCI_VENDOR_ID_VORTEX: return "VORTEX";
case PCI_VENDOR_ID_EF: return "Efficient Networks";
case PCI_VENDOR_ID_FORE: return "Fore Systems";
@@ -782,6 +796,7 @@ static const char *pci_strvendor(unsigned int vendor)
case PCI_VENDOR_ID_AVANCE: return "Avance";
case PCI_VENDOR_ID_NETVIN: return "NetVin";
case PCI_VENDOR_ID_S3: return "S3 Inc.";
+ case PCI_VENDOR_ID_DCI: return "Decision Computer Int.";
case PCI_VENDOR_ID_GENROCO: return "Genroco";
case PCI_VENDOR_ID_INTEL: return "Intel";
case PCI_VENDOR_ID_KTI: return "KTI";
@@ -882,7 +897,7 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
if (len + 40 > size) {
return -1;
}
- len += sprintf(buf + len, "IRQ %x. ", dev->irq);
+ len += sprintf(buf + len, "IRQ %d. ", dev->irq);
}
if (dev->master) {
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0f62a76c1..599253933 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -28,6 +28,9 @@
#endif
struct pci_bus pci_root;
+#ifdef CONFIG_VISWS
+struct pci_bus pci_other;
+#endif
struct pci_dev *pci_devices = NULL;
static struct pci_dev **pci_last_dev_p = &pci_devices;
static int pci_reverse __initdata = 0;
@@ -382,6 +385,11 @@ __initfunc(void pci_init(void))
memset(&pci_root, 0, sizeof(pci_root));
pci_root.subordinate = pci_scan_bus(&pci_root);
+#ifdef CONFIG_VISWS
+ pci_other.number = 1; /* XXX unless bridge(s) on pci_root */
+ pci_other.subordinate = pci_scan_bus(&pci_other);
+ pci_root.next = &pci_other;
+#endif
/* give BIOS a chance to apply platform specific fixes: */
pcibios_fixup();
diff --git a/drivers/pci/pcisyms.c b/drivers/pci/pcisyms.c
index f7399c9fb..f26adfc7c 100644
--- a/drivers/pci/pcisyms.c
+++ b/drivers/pci/pcisyms.c
@@ -9,6 +9,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <asm/dma.h> /* isa_dma_bridge_buggy */
EXPORT_SYMBOL(pcibios_present);
EXPORT_SYMBOL(pcibios_read_config_byte);
@@ -38,3 +39,10 @@ EXPORT_SYMBOL(pci_proc_detach_device);
EXPORT_SYMBOL(pcibios_find_class);
EXPORT_SYMBOL(pcibios_find_device);
+
+/* Quirk info */
+
+#ifdef CONFIG_PCI_QUIRKS
+EXPORT_SYMBOL(isa_dma_bridge_buggy);
+#endif
+
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 77ef16f91..3fe633030 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -125,6 +125,25 @@ __initfunc(static void quirk_passive_release(struct pci_dev *dev, int arg))
}
}
+/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
+ but VIA don't answer queries. If you happen to have good contacts at VIA
+ ask them for me please -- Alan
+
+ This appears to be BIOS not version dependent. So presumably there is a
+ chipset level fix */
+
+
+int isa_dma_bridge_buggy = 0; /* Exported */
+
+__initfunc(static void quirk_isa_dma_hangs(struct pci_dev *dev, int arg))
+{
+ if(!isa_dma_bridge_buggy)
+ {
+ isa_dma_bridge_buggy=1;
+ printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
+ }
+}
+
typedef void (*quirk_handler)(struct pci_dev *, int);
@@ -141,7 +160,8 @@ static struct quirk_name quirk_names[] __initdata = {
#ifdef CONFIG_PCI_OPTIMIZE
{ quirk_bridge, "Bridge optimization" },
#endif
- { quirk_passive_release, "Passive release enable" },
+ { quirk_passive_release,"Passive release enable" },
+ { quirk_isa_dma_hangs, "Work around ISA DMA hangs" },
};
@@ -176,6 +196,12 @@ static struct quirk_info quirk_list[] __initdata = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82430, quirk_bridge, 0x00 },
#endif
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release, 0x00 },
+ /*
+ * Its not totally clear which chipsets are the problematic ones
+ * This is the 82C586 variants. At the moment the 596 is an unknown
+ * quantity
+ */
+ { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs, 0x00 },
};
__initfunc(void pci_quirks_init(void))
diff --git a/drivers/pnp/parport_probe.c b/drivers/pnp/parport_probe.c
index 32188af9e..8ae499311 100644
--- a/drivers/pnp/parport_probe.c
+++ b/drivers/pnp/parport_probe.c
@@ -54,8 +54,10 @@ static long read_polled(struct parport *port, char *buf,
unsigned int count = 0;
unsigned char z=0;
unsigned char Byte=0;
+ unsigned long igiveupat=jiffies+5*HZ;
- for (i=0; ; i++) {
+ for (i=0; time_before(jiffies, igiveupat); i++) {
+ /* if(current->need_resched) schedule(); */
parport_write_control(port, parport_read_control(port) | 2); /* AutoFeed high */
if (parport_wait_peripheral(port, 0x40, 0)) {
#ifdef DEBUG_PROBE
@@ -103,13 +105,13 @@ int parport_probe(struct parport *port, char *buffer, int len)
parport_claim_or_block(dev);
switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
- case 1:
+ case 2:
current->state=TASK_INTERRUPTIBLE;
/* HACK: wait 10ms because printer seems to ack wrong */
schedule_timeout((HZ+99)/100);
result = read_polled(port, buffer, len);
break;
- case 0:
+ default:
result = -EIO;
break;
}
diff --git a/drivers/sbus/audio/amd7930.c b/drivers/sbus/audio/amd7930.c
index 4a0064f55..9b71e0a80 100644
--- a/drivers/sbus/audio/amd7930.c
+++ b/drivers/sbus/audio/amd7930.c
@@ -1021,7 +1021,7 @@ static int amd7930_ioctl(struct inode * inode, struct file * file,
*
* 0 - successful reception
* non-0 - error value from chip's DER (D-Channel Error Register):
- * 1 - recieved packet abort
+ * 1 - received packet abort
* 2 - framing error; non-integer number of bytes received
* 8 - FCS error; CRC sequence indicated corrupted data
* 16 - overflow error; packet exceeded size of buffer
diff --git a/drivers/sbus/audio/dbri.h b/drivers/sbus/audio/dbri.h
index af3a8a4d7..363d0b225 100644
--- a/drivers/sbus/audio/dbri.h
+++ b/drivers/sbus/audio/dbri.h
@@ -305,7 +305,7 @@ struct dbri {
#define DBRI_RD_M (1<<14) /* Marker interrupt */
#define DBRI_RD_BCNT(v) v /* Buffer size */
#define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */
-#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte recieved */
+#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */
#define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */
#define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */
#define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
index f445a14b2..0121a03e7 100644
--- a/drivers/sbus/char/bpp.c
+++ b/drivers/sbus/char/bpp.c
@@ -337,8 +337,8 @@ static int wait_for(unsigned short set, unsigned short clr,
* responds real good. The first while loop guesses an expire
* time accounting for possible wraparound of jiffies.
*/
- while (extime <= jiffies) extime = jiffies + 1;
- while ( (jiffies < extime)
+ while (time_after_eq(jiffies, extime) extime = jiffies + 1;
+ while ( (time_before(jiffies, extime))
&& (((pins & set) != set) || ((pins & clr) != 0)) ) {
pins = get_pins(minor);
}
diff --git a/drivers/sbus/char/sab82532.c b/drivers/sbus/char/sab82532.c
index 3f0924525..1ea317726 100644
--- a/drivers/sbus/char/sab82532.c
+++ b/drivers/sbus/char/sab82532.c
@@ -1676,7 +1676,7 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
schedule_timeout(char_time);
if (signal_pending(current))
break;
- if (timeout && (orig_jiffies + timeout) < jiffies)
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
current->state = TASK_RUNNING;
diff --git a/drivers/sbus/char/su.c b/drivers/sbus/char/su.c
index b05acc314..b4ab6693f 100644
--- a/drivers/sbus/char/su.c
+++ b/drivers/sbus/char/su.c
@@ -1818,7 +1818,7 @@ su_wait_until_sent(struct tty_struct *tty, int timeout)
schedule_timeout(char_time);
if (signal_pending(current))
break;
- if (timeout && ((orig_jiffies + timeout) < jiffies))
+ if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
current->state = TASK_RUNNING;
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c
index 68cfc4405..8302316aa 100644
--- a/drivers/sbus/char/vfc_i2c.c
+++ b/drivers/sbus/char/vfc_i2c.c
@@ -156,7 +156,7 @@ int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, char mode)
switch(mode) {
case VFC_I2C_READ:
dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1);
- VFC_I2C_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n",
+ VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
dev->instance,addr | 0x1));
break;
case VFC_I2C_WRITE:
@@ -255,7 +255,7 @@ int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr,
if(!count) last=1;
if((ret=vfc_i2c_recv_byte(dev,buf,last))) {
printk(KERN_ERR "vfc%d: "
- "VFC error while recieving byte\n",
+ "VFC error while receiving byte\n",
dev->instance);
dev->regs->i2c_s1=SEND_I2C_STOP;
ret=-EINVAL;
diff --git a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c
index 7c6c4d80e..250830250 100644
--- a/drivers/scsi/AM53C974.c
+++ b/drivers/scsi/AM53C974.c
@@ -756,7 +756,7 @@ __initfunc(static int AM53C974_init(Scsi_Host_Template * tpnt, struct pci_dev *p
(search->irq != instance->irq) || (search == instance));
search = search->next);
if (!search) {
- if (request_irq(instance->irq, do_AM53C974_intr, SA_INTERRUPT, "AM53C974", NULL)) {
+ if (request_irq(instance->irq, do_AM53C974_intr, SA_SHIRQ, "AM53C974", instance)) {
printk("scsi%d: IRQ%d not free, detaching\n", instance->host_no, instance->irq);
scsi_unregister(instance);
return 0;
@@ -2458,7 +2458,7 @@ int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int reset_flags)
*/
int AM53C974_release(struct Scsi_Host *shp)
{
- free_irq(shp->irq, NULL);
+ free_irq(shp->irq, shp);
scsi_unregister(shp);
return 0;
}
diff --git a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx
index e7af08c0c..0f9c85de5 100644
--- a/drivers/scsi/ChangeLog.ncr53c8xx
+++ b/drivers/scsi/ChangeLog.ncr53c8xx
@@ -1,3 +1,16 @@
+Sat Jan 16 17:30 1998 Gerard Roudier (groudier@club-internet.fr)
+ * revision 3.1f
+ - Some PCI fix-ups not needed any more for PPC (from Cort).
+ - Cache line size set to 16 DWORDS for Sparc (from DSM).
+ - Waiting list look-up didn't work for the first command of the list.
+ - Remove 2 useless lines of code.
+
+Sun Dec 13 18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+ * revision 3.1e
+ - Same work-around as for the 53c876 rev <= 0x15 for 53c896 rev 1:
+ Disable overlapped arbitration. This will not make difference
+ since the chip has on-chip RAM.
+
Thu Nov 26 22:00 1998 Gerard Roudier (groudier@club-internet.fr)
* revision 3.1d
- The SISL RAID change requires now remap_pci_mem() stuff to be
diff --git a/drivers/scsi/Config.in b/drivers/scsi/Config.in
index 0bd37f65f..686df3085 100644
--- a/drivers/scsi/Config.in
+++ b/drivers/scsi/Config.in
@@ -19,6 +19,7 @@ mainmenu_option next_comment
comment 'SCSI low-level drivers'
dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
+dep_tristate 'ACARD SCSI support' CONFIG_SCSI_ACARD $CONFIG_SCSI
dep_tristate 'Adaptec AHA152X/2825 support' CONFIG_SCSI_AHA152X $CONFIG_SCSI
dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 $CONFIG_SCSI
dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
@@ -34,20 +35,22 @@ fi
dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
+dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI
+
dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
bool ' Omit FlashPoint support' CONFIG_SCSI_OMIT_FLASHPOINT
fi
dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI
-dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
-dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
if [ "$CONFIG_SCSI_EATA" != "n" ]; then
bool ' enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE
bool ' enable elevator sorting' CONFIG_SCSI_EATA_LINKED_COMMANDS
int ' maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
fi
-dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
+dep_tristate 'EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
+dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
+dep_tristate 'Future Domain 16xx SCSI/AHA-2920A support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
if [ "$CONFIG_MCA" = "y" ]; then
if [ "$CONFIG_SCSI" = "y" ]; then
bool 'Future Domain MCS-600/700 SCSI support' CONFIG_SCSI_FD_MCS
@@ -55,19 +58,23 @@ if [ "$CONFIG_MCA" = "y" ]; then
fi
dep_tristate 'GDT SCSI Disk Array Controller support' CONFIG_SCSI_GDTH $CONFIG_SCSI
dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
-if [ "$CONFIG_PARPORT" != "n" ]; then
- dep_tristate 'IOMEGA Parallel Port ZIP drive SCSI support' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
- if [ "$CONFIG_SCSI_PPA" != "n" ]; then
- bool ' Pedantic EPP-checking' CONFIG_SCSI_PPA_HAVE_PEDANTIC
- fi
- dep_tristate 'IOMEGA ZIP Plus drive SCSI support' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
-fi
if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
bool ' Enable NCR53c400 extensions' CONFIG_SCSI_GENERIC_NCR53C400
choice 'NCR5380/53c400 mapping method (use Port for T130B)' \
"Port CONFIG_SCSI_G_NCR5380_PORT \
Memory CONFIG_SCSI_G_NCR5380_MEM" Port
fi
+if [ "$CONFIG_PCI" = "y" ]; then
+ dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI
+fi
+if [ "$CONFIG_PARPORT" != "n" ]; then
+ dep_tristate 'IOMEGA parallel port (ppa - older drives)' CONFIG_SCSI_PPA $CONFIG_SCSI $CONFIG_PARPORT
+ dep_tristate 'IOMEGA parallel port (imm - newer drives)' CONFIG_SCSI_IMM $CONFIG_SCSI $CONFIG_PARPORT
+ if [ "$CONFIG_SCSI_PPA" != "n" -o "$CONFIG_SCSI_IMM" != "n" ]; then
+ bool ' ppa/imm option - Use slow (but safe) EPP-16' CONFIG_SCSI_IZIP_EPP16
+ bool ' ppa/imm option - Assume slow parport control register' CONFIG_SCSI_IZIP_SLOW_CTR
+ fi
+fi
dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI
@@ -100,6 +107,9 @@ if [ "$CONFIG_MCA" = "y" ]; then
bool ' Reset SCSI-devices at boottime' CONFIG_IBMMCA_SCSI_DEV_RESET
fi
fi
+if [ "$CONFIG_MCA" = "y" ]; then
+ dep_tristate 'NCR MCA 53C9x SCSI support' CONFIG_SCSI_MCA_53C9X $CONFIG_SCSI
+fi
dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
dep_tristate 'PCI2000 support' CONFIG_SCSI_PCI2000 $CONFIG_SCSI
dep_tristate 'PCI2220i support' CONFIG_SCSI_PCI2220I $CONFIG_SCSI
@@ -107,6 +117,7 @@ dep_tristate 'PSI240i support' CONFIG_SCSI_PSI240I $CONFIG_SCSI
dep_tristate 'Qlogic FAS SCSI support' CONFIG_SCSI_QLOGIC_FAS $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate 'Qlogic ISP SCSI support' CONFIG_SCSI_QLOGIC_ISP $CONFIG_SCSI
+# dep_tristate 'Qlogic ISP FC SCSI support' CONFIG_SCSI_QLOGIC_FC $CONFIG_SCSI
fi
dep_tristate 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE $CONFIG_SCSI
if [ "$CONFIG_PCI" = "y" ]; then
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 73c433ff1..28c11f7b6 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -41,9 +41,7 @@ ifeq ($(CONFIG_SCSI),y)
endif
L_OBJS += scsi_n_syms.o hosts.o scsi_ioctl.o constants.o scsicam.o
L_OBJS += scsi_error.o scsi_obsolete.o scsi_queue.o
- ifeq ($(CONFIG_PROC_FS),y)
- L_OBJS += scsi_proc.o
- endif
+ L_OBJS += scsi_proc.o
else
ifeq ($(CONFIG_SCSI),m)
MIX_OBJS += scsi_syms.o
@@ -195,6 +193,14 @@ else
endif
endif
+ifeq ($(CONFIG_SCSI_MCA_53C9X),y)
+L_OBJS += NCR53C9x.o mca_53c9x.o
+else
+ ifeq ($(CONFIG_SCSI_MCA_53C9X),m)
+ M_OBJS += NCR53C9x.o mca_53c9x.o
+ endif
+endif
+
ifeq ($(CONFIG_CYBERSTORM_SCSI),y)
L_OBJS += NCR53C9x.o cyberstorm.o
else
@@ -276,6 +282,29 @@ else
endif
endif
+ifeq ($(CONFIG_SCSI_ACARD),y)
+L_OBJS += atp870u.o
+else
+ ifeq ($(CONFIG_SCSI_ACARD),m)
+ M_OBJS += atp870u.o
+ endif
+endif
+
+ifeq ($(CONFIG_SCSI_INITIO),y)
+L_OBJS += initio.o
+else
+ ifeq ($(CONFIG_SCSI_INITIO),m)
+ M_OBJS += initio.o
+ endif
+endif
+
+ifeq ($(CONFIG_SCSI_QLOGIC_FC),y)
+L_OBJS += qlogicfc.o
+else
+ ifeq ($(CONFIG_SCSI_QLOGIC_FC),m)
+ M_OBJS += qlogicfc.o
+ endif
+endif
ifeq ($(CONFIG_SCSI_AHA152X),y)
L_OBJS += aha152x.o
@@ -539,6 +568,14 @@ else
endif
endif
+ifeq ($(CONFIG_SCSI_MEGARAID),y)
+L_OBJS += megaraid.o
+else
+ ifeq ($(CONFIG_SCSI_MEGARAID),m)
+ M_OBJS += megaraid.o
+ endif
+endif
+
ifeq ($(CONFIG_BLK_DEV_IDESCSI),y)
L_OBJS += ide-scsi.o
else
@@ -574,6 +611,15 @@ include $(TOPDIR)/Rules.make
53c7xx.o : 53c7xx_d.h 53c7xx.c
$(CC) $(CFLAGS) -c 53c7xx.c
+initio.o: ini9100u.c i91uscsi.c
+ $(CC) $(CFLAGS) -c ini9100u.c -o ini9100u.o
+ $(CC) $(CFLAGS) -c i91uscsi.c -o i91uscsi.o
+ $(LD) -r -o initio.o ini9100u.o i91uscsi.o
+ rm -f ini9100u.o i91uscsi.o
+
+megaraid.o: megaraid.c
+ $(CC) $(CFLAGS) -c megaraid.c
+
scsi_mod.o: $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \
scsicam.o scsi_proc.o scsi_error.o scsi_obsolete.o scsi_queue.o
$(LD) $(LD_RFLAG) -r -o $@ $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o \
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index bba8f70de..3aff27f32 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -1919,7 +1919,7 @@ part2:
spin_lock_irq(&io_request_lock);
if (time_after_eq(jiffies, timeout)) {
- printk("scsi%d: timeout at NCR5380.c:%d\n", __LINE__);
+ printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
return -1;
}
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index f3b693255..c997cba65 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -6,6 +6,9 @@
*
* Most DMA dependencies put in driver specific files by
* Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Set up to use GETREG/SETREG (preprocessor macros in NCR53c9x.h) by
+ * Tymm Twillman (tymm@coe.missouri.edu)
*/
/* TODO:
@@ -27,6 +30,7 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+
#include <linux/init.h>
#include "scsi.h"
@@ -297,7 +301,7 @@ extern inline void esp_cmd(struct NCR_ESP *esp, struct ESP_regs *eregs,
esp->espcmdlog[esp->espcmdent] = cmd;
esp->espcmdent = (esp->espcmdent + 1) & 31;
#endif
- eregs->esp_cmd = cmd;
+ SETREG(eregs->esp_cmnd, cmd);
}
/* How we use the various Linux SCSI data structures for operation.
@@ -400,7 +404,7 @@ static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
*/
esp->max_period = ((35 * esp->ccycle) / 1000);
if(esp->erev == fast) {
- version = eregs->esp_uid;
+ version = GETREG(eregs->esp_uid);
family_code = (version & 0xf8) >> 3;
#ifdef SYMBIOS_HACK
if (version == 0 && family_code == 0)
@@ -432,25 +436,25 @@ static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
}
/* Reload the configuration registers */
- eregs->esp_cfact = esp->cfact;
- eregs->esp_stp = 0;
- eregs->esp_soff = 0;
- eregs->esp_timeo = esp->neg_defp;
+ SETREG(eregs->esp_cfact, esp->cfact);
+ SETREG(eregs->esp_stp, 0);
+ SETREG(eregs->esp_soff, 0);
+ SETREG(eregs->esp_timeo, esp->neg_defp);
esp->max_period = (esp->max_period + 3)>>2;
esp->min_period = (esp->min_period + 3)>>2;
- eregs->esp_cfg1 = esp->config1;
+ SETREG(eregs->esp_cfg1, esp->config1);
switch(esp->erev) {
case esp100:
/* nothing to do */
break;
case esp100a:
- eregs->esp_cfg2 = esp->config2;
+ SETREG(eregs->esp_cfg2, esp->config2);
break;
case esp236:
/* Slow 236 */
- eregs->esp_cfg2 = esp->config2;
- eregs->esp_cfg3 = esp->config3[0];
+ SETREG(eregs->esp_cfg2, esp->config2);
+ SETREG(eregs->esp_cfg3, esp->config3[0]);
break;
case fashme:
esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
@@ -458,7 +462,7 @@ static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
case fas216:
case fas236:
/* Fast 236 or HME */
- eregs->esp_cfg2 = esp->config2;
+ SETREG(eregs->esp_cfg2, esp->config2);
for(i=0; i<8; i++) {
if(esp->erev == fashme)
esp->config3[i] |=
@@ -466,7 +470,7 @@ static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
else
esp->config3[i] |= ESP_CONFIG3_FCLK;
}
- eregs->esp_cfg3 = esp->config3[0];
+ SETREG(eregs->esp_cfg3, esp->config3[0]);
if(esp->erev == fashme) {
esp->radelay = 80;
} else {
@@ -478,10 +482,10 @@ static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
break;
case fas100a:
/* Fast 100a */
- eregs->esp_cfg2 = esp->config2;
+ SETREG(eregs->esp_cfg2, esp->config2);
for(i=0; i<8; i++)
esp->config3[i] |= ESP_CONFIG3_FCLOCK;
- eregs->esp_cfg3 = esp->config3[0];
+ SETREG(eregs->esp_cfg3, esp->config3[0]);
esp->radelay = 32;
break;
default:
@@ -490,7 +494,7 @@ static inline void esp_reset_esp(struct NCR_ESP *esp, struct ESP_regs *eregs)
};
/* Eat any bitrot in the chip */
- trash = eregs->esp_intrpt;
+ trash = GETREG(eregs->esp_intrpt);
udelay(100);
}
@@ -507,13 +511,13 @@ inline void esp_bootup_reset(struct NCR_ESP *esp, struct ESP_regs *eregs)
esp_reset_esp(esp, eregs);
/* Reset the SCSI bus, but tell ESP not to generate an irq */
- eregs->esp_cfg1 |= ESP_CONFIG1_SRRDISAB;
+ SETREG(eregs->esp_cfg1, GETREG(eregs->esp_cfg1) | ESP_CONFIG1_SRRDISAB);
esp_cmd(esp, eregs, ESP_CMD_RS);
udelay(400);
- eregs->esp_cfg1 = esp->config1;
+ SETREG(eregs->esp_cfg1, esp->config1);
/* Eat any bitrot in the chip and we are done... */
- trash = eregs->esp_intrpt;
+ trash = GETREG(eregs->esp_intrpt);
}
/* Allocate structure and insert basic data such as SCSI chip frequency
@@ -650,19 +654,21 @@ void esp_initialize(struct NCR_ESP *esp)
/* Probe the revision of this esp */
esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
- eregs->esp_cfg2 = esp->config2;
+ SETREG(eregs->esp_cfg2, esp->config2);
#ifndef SYMBIOS_HACK
- if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
+ if((GETREG(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=
(ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
printk("NCR53C90(esp100) detected\n");
esp->erev = esp100;
} else {
#endif
- eregs->esp_cfg2 = esp->config2 = 0;
- eregs->esp_cfg3 = 0;
- eregs->esp_cfg3 = esp->config3[0] = 5;
+ esp->config2 = 0;
+ SETREG(eregs->esp_cfg2, esp->config2);
+ SETREG(eregs->esp_cfg3, 0);
+ esp->config3[0] = 5;
+ SETREG(eregs->esp_cfg3, esp->config3[0]);
#ifndef SYMBIOS_HACK
- if(eregs->esp_cfg3 != 5) {
+ if(GETREG(eregs->esp_cfg3) != 5) {
printk("NCR53C90A(esp100a) detected\n");
esp->erev = esp100a;
} else {
@@ -673,19 +679,21 @@ void esp_initialize(struct NCR_ESP *esp)
for(target=0; target<8; target++)
esp->config3[target] = 0;
- eregs->esp_cfg3 = 0;
+ SETREG(eregs->esp_cfg3, 0);
#ifndef SYMBIOS_HACK
if(ccf > ESP_CCF_F5) {
#endif
printk("NCR53C9XF(espfast) detected\n");
esp->erev = fast;
- eregs->esp_cfg2 = esp->config2 = 0;
+ esp->config2 = 0;
+ SETREG(eregs->esp_cfg2, esp->config2);
esp->sync_defp = SYNC_DEFP_FAST;
#ifndef SYMBIOS_HACK
} else {
printk("NCR53C9x(esp236) detected\n");
esp->erev = esp236;
- eregs->esp_cfg2 = esp->config2 = 0;
+ esp->config2 = 0;
+ SETREG(eregs->esp_cfg2, esp->config2);
}
}
#endif
@@ -1193,14 +1201,14 @@ after_nego_msg_built:
/* HME sucks... */
if(esp->erev == fashme)
- eregs->esp_busid = (target & 0xf) |
- (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+ SETREG(eregs->esp_busid, (target & 0xf) |
+ (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
else
- eregs->esp_busid = (target & 7);
- eregs->esp_soff = SDptr->sync_max_offset;
- eregs->esp_stp = SDptr->sync_min_period;
+ SETREG(eregs->esp_busid, (target & 7));
+ SETREG(eregs->esp_soff, SDptr->sync_max_offset);
+ SETREG(eregs->esp_stp, SDptr->sync_min_period);
if(esp->erev > esp100a)
- eregs->esp_cfg3 = esp->config3[target];
+ SETREG(eregs->esp_cfg3, esp->config3[target]);
i = (cmdp - esp->esp_command);
@@ -1209,7 +1217,7 @@ after_nego_msg_built:
int j = 0;
for(;j<i;j++)
- eregs->esp_fdata = esp->esp_command[j];
+ SETREG(eregs->esp_fdata, esp->esp_command[j]);
the_esp_command &= ~ESP_CMD_DMA;
/* Tell ESP to "go". */
@@ -1219,16 +1227,16 @@ after_nego_msg_built:
esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
/* Set up the HME counters */
- eregs->esp_tclow = i;
- eregs->esp_tcmed = 0;
- eregs->fas_rlo = 0;
- eregs->fas_rhi = 0;
+ SETREG(eregs->esp_tclow, i);
+ SETREG(eregs->esp_tcmed, 0);
+ SETREG(eregs->fas_rlo, 0);
+ SETREG(eregs->fas_rhi, 0);
esp_cmd(esp, eregs, the_esp_command);
esp->dma_init_write(esp, esp->esp_command_dvma, 16);
} else {
/* Set up the ESP counters */
- eregs->esp_tclow = i;
- eregs->esp_tcmed = 0;
+ SETREG(eregs->esp_tclow, i);
+ SETREG(eregs->esp_tcmed, 0);
esp->dma_init_write(esp, esp->esp_command_dvma, i);
/* Tell ESP to "go". */
@@ -1341,7 +1349,8 @@ static inline void esp_dump_state(struct NCR_ESP *esp,
ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
esp->esp_id, esp->sreg, esp->seqreg, esp->ireg));
ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
- esp->esp_id, eregs->esp_status, eregs->esp_sstep, eregs->esp_intrpt));
+ esp->esp_id, GETREG(eregs->esp_status),
+ GETREG(eregs->esp_sstep), GETREG(eregs->esp_intrpt)));
#ifdef DEBUG_ESP_CMDS
printk("esp%d: last ESP cmds [", esp->esp_id);
i = (esp->espcmdent - 1) & 31;
@@ -1549,20 +1558,23 @@ static inline void hme_fifo_hwbug_workaround(struct NCR_ESP *esp,
return;
} else {
unsigned long count = 0;
- unsigned long fcnt = eregs->esp_fflags & ESP_FF_FBYTES;
+ unsigned long fcnt = GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
/* The HME stores bytes in multiples of 2 in the fifo. */
ESPHME(("hme_fifo[fcnt=%d", (int)fcnt));
while(fcnt) {
- esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
- esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
+ esp->hme_fifo_workaround_buffer[count++] =
+ GETREG(eregs->esp_fdata);
+ esp->hme_fifo_workaround_buffer[count++] =
+ GETREG(eregs->esp_fdata);
ESPHME(("<%02x,%02x>", esp->hme_fifo_workaround_buffer[count-2], esp->hme_fifo_workaround_buffer[count-1]));
fcnt--;
}
- if(eregs->esp_status2 & ESP_STAT2_F1BYTE) {
+ if(GETREG(eregs->esp_status2) & ESP_STAT2_F1BYTE) {
ESPHME(("<poke_byte>"));
- eregs->esp_fdata = 0;
- esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
+ SETREG(eregs->esp_fdata, 0);
+ esp->hme_fifo_workaround_buffer[count++] =
+ GETREG(eregs->esp_fdata);
ESPHME(("<%02x,0x00>", esp->hme_fifo_workaround_buffer[count-1]));
ESPHME(("CMD_FLUSH"));
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
@@ -1579,8 +1591,8 @@ static inline void hme_fifo_push(struct NCR_ESP *esp, struct ESP_regs *eregs,
{
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
while(count) {
- eregs->esp_fdata = *bytes++;
- eregs->esp_fdata = 0;
+ SETREG(eregs->esp_fdata, *bytes++);
+ SETREG(eregs->esp_fdata, 0);
count--;
}
}
@@ -1596,7 +1608,7 @@ static inline int skipahead1(struct NCR_ESP *esp, struct ESP_regs *eregs,
if(esp->dma_irq_p(esp)) {
/* Yes, we are able to save an interrupt. */
- esp->sreg = eregs->esp_status;
+ esp->sreg = GETREG(eregs->esp_status);
if(esp->erev == fashme) {
/* This chip is really losing. */
ESPHME(("HME["));
@@ -1608,7 +1620,7 @@ static inline int skipahead1(struct NCR_ESP *esp, struct ESP_regs *eregs,
ESPHME(("fifo_workaround]"));
hme_fifo_hwbug_workaround(esp, eregs);
}
- esp->ireg = eregs->esp_intrpt;
+ esp->ireg = GETREG(eregs->esp_intrpt);
esp->sreg &= ~(ESP_STAT_INTR);
if(!(esp->ireg & ESP_INTR_SR))
return 0;
@@ -1630,7 +1642,7 @@ static inline int skipahead2(struct NCR_ESP *esp,
return 0;
if(esp->dma_irq_p(esp)) {
/* Yes, we are able to save an interrupt. */
- esp->sreg = eregs->esp_status;
+ esp->sreg = GETREG(eregs->esp_status);
if(esp->erev == fashme) {
/* This chip is really losing. */
ESPHME(("HME["));
@@ -1643,7 +1655,7 @@ static inline int skipahead2(struct NCR_ESP *esp,
ESPHME(("fifo_workaround]"));
hme_fifo_hwbug_workaround(esp, eregs);
}
- esp->ireg = eregs->esp_intrpt;
+ esp->ireg = GETREG(eregs->esp_intrpt);
esp->sreg &= ~(ESP_STAT_INTR);
if(!(esp->ireg & ESP_INTR_SR))
return 0;
@@ -1658,18 +1670,18 @@ static inline int skipahead2(struct NCR_ESP *esp,
/* Misc. esp helper routines. */
static inline void esp_setcount(struct ESP_regs *eregs, int cnt, int hme)
{
- eregs->esp_tclow = (cnt & 0xff);
- eregs->esp_tcmed = ((cnt >> 8) & 0xff);
+ SETREG(eregs->esp_tclow, (cnt & 0xff));
+ SETREG(eregs->esp_tcmed, ((cnt >> 8) & 0xff));
if(hme) {
- eregs->fas_rlo = 0;
- eregs->fas_rhi = 0;
+ SETREG(eregs->fas_rlo, 0);
+ SETREG(eregs->fas_rhi, 0);
}
}
static inline int esp_getcount(struct ESP_regs *eregs)
{
- return (((eregs->esp_tclow)&0xff) |
- (((eregs->esp_tcmed)&0xff) << 8));
+ return (((GETREG(eregs->esp_tclow))&0xff) |
+ (((GETREG(eregs->esp_tcmed))&0xff) << 8));
}
static inline int fcount(struct NCR_ESP *esp, struct ESP_regs *eregs)
@@ -1677,7 +1689,7 @@ static inline int fcount(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(esp->erev == fashme)
return esp->hme_fifo_workaround_count;
else
- return eregs->esp_fflags & ESP_FF_FBYTES;
+ return GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
}
static inline int fnzero(struct NCR_ESP *esp, struct ESP_regs *eregs)
@@ -1685,7 +1697,7 @@ static inline int fnzero(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(esp->erev == fashme)
return 0;
else
- return eregs->esp_fflags & ESP_FF_ONOTZERO;
+ return GETREG(eregs->esp_fflags) & ESP_FF_ONOTZERO;
}
/* XXX speculative nops unnecessary when continuing amidst a data phase
@@ -1719,8 +1731,8 @@ static inline int esp100_sync_hwbug(struct NCR_ESP *esp, struct ESP_regs *eregs,
{
/* Do not touch this piece of code. */
if((!(esp->erev == esp100)) ||
- (!(sreg_datainp((esp->sreg = eregs->esp_status)) && !fifocnt) &&
- !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
+ (!(sreg_datainp((esp->sreg = GETREG(eregs->esp_status))) && !fifocnt)
+ && !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
if(sp->SCp.phase == in_dataout)
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
return 0;
@@ -1747,7 +1759,7 @@ static inline int esp100_reconnect_hwbug(struct NCR_ESP *esp,
if(esp->erev != esp100)
return 0;
- junk = eregs->esp_intrpt;
+ junk = GETREG(eregs->esp_intrpt);
if(junk & ESP_INTR_SR)
return 1;
@@ -1772,7 +1784,7 @@ static inline int reconnect_target(struct NCR_ESP *esp, struct ESP_regs *eregs)
*/
targ = esp->hme_fifo_workaround_buffer[0];
} else {
- it = eregs->esp_fdata;
+ it = GETREG(eregs->esp_fdata);
if(!(it & me))
return -1;
it &= ~me;
@@ -1796,7 +1808,7 @@ static inline int reconnect_lun(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(esp->erev == fashme)
lun = esp->hme_fifo_workaround_buffer[1];
else
- lun = eregs->esp_fdata;
+ lun = GETREG(eregs->esp_fdata);
if(esp->sreg & ESP_STAT_PERR)
return 0;
if((lun & 0x40) || !(lun & 0x80))
@@ -1811,13 +1823,13 @@ static inline void esp_connect(struct NCR_ESP *esp, struct ESP_regs *eregs,
Scsi_Cmnd *sp)
{
Scsi_Device *dp = sp->device;
- eregs->esp_soff = dp->sync_max_offset;
- eregs->esp_stp = dp->sync_min_period;
+ SETREG(eregs->esp_soff, dp->sync_max_offset);
+ SETREG(eregs->esp_stp, dp->sync_min_period);
if(esp->erev > esp100a)
- eregs->esp_cfg3 = esp->config3[sp->target];
+ SETREG(eregs->esp_cfg3, esp->config3[sp->target]);
if(esp->erev == fashme)
- eregs->esp_busid = (sp->target & 0xf) |
- (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+ SETREG(eregs->esp_busid, (sp->target & 0xf) |
+ (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
esp->current_SC = sp;
}
@@ -1839,7 +1851,8 @@ static inline void esp_reconnect(struct NCR_ESP *esp, Scsi_Cmnd *sp)
static inline int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs)
{
/* Must be very careful with the fifo on the HME */
- if((esp->erev != fashme) || !(eregs->esp_status2 & ESP_STAT2_FEMPTY))
+ if((esp->erev != fashme) || !(GETREG(eregs->esp_status2) &
+ ESP_STAT2_FEMPTY))
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
esp_maybe_nop(esp, eregs);
esp_cmd(esp, eregs, ESP_CMD_TI);
@@ -1961,7 +1974,7 @@ static inline int esp_do_data_finale(struct NCR_ESP *esp,
* will move and count 16-bit quantities during wide data.
* SMCC _and_ Qlogic can both bite me.
*/
- fifocnt = eregs->esp_fflags & ESP_FF_FBYTES;
+ fifocnt = GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
if(esp->erev != fashme)
ecount = esp_getcount(eregs);
bytes_sent = esp->current_transfer_size;
@@ -2360,16 +2373,18 @@ static int esp_do_phase_determine(struct NCR_ESP *esp,
if(esp->do_pio_cmds){
esp_advance_phase(SCptr, in_status);
esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
- while(!(esp->eregs->esp_status & ESP_STAT_INTR));
- esp->esp_command[0] = eregs->esp_fdata;
- while(!(esp->eregs->esp_status & ESP_STAT_INTR));
- esp->esp_command[1] = eregs->esp_fdata;
+ while(!(GETREG(esp->eregs->esp_status)
+ & ESP_STAT_INTR));
+ esp->esp_command[0] = GETREG(eregs->esp_fdata);
+ while(!(GETREG(esp->eregs->esp_status)
+ & ESP_STAT_INTR));
+ esp->esp_command[1] = GETREG(eregs->esp_fdata);
} else {
if(esp->erev != fashme) {
esp->esp_command[0] = 0xff;
esp->esp_command[1] = 0xff;
- eregs->esp_tclow = 2;
- eregs->esp_tcmed = 0;
+ SETREG(eregs->esp_tclow, 2);
+ SETREG(eregs->esp_tcmed, 0);
esp->dma_init_read(esp, esp->esp_command_dvma, 2);
esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_ICCSEQ);
} else {
@@ -2456,11 +2471,11 @@ static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs)
int cmd_bytes_sent, fcnt;
if(esp->erev != fashme)
- esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS);
+ esp->seqreg = (GETREG(eregs->esp_sstep) & ESP_STEP_VBITS);
if(esp->erev == fashme)
fcnt = esp->hme_fifo_workaround_count;
else
- fcnt = (eregs->esp_fflags & ESP_FF_FBYTES);
+ fcnt = (GETREG(eregs->esp_fflags) & ESP_FF_FBYTES);
cmd_bytes_sent = esp->dma_bytes_sent(esp, fcnt);
if(esp->dma_invalidate)
esp->dma_invalidate(esp);
@@ -2695,9 +2710,9 @@ static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs)
esp_print_seqreg(esp->seqreg);
printk("\n");
printk("esp%d: New -- ", esp->esp_id);
- esp->sreg = eregs->esp_status;
- esp->seqreg = eregs->esp_sstep;
- esp->ireg = eregs->esp_intrpt;
+ esp->sreg = GETREG(eregs->esp_status);
+ esp->seqreg = GETREG(eregs->esp_sstep);
+ esp->ireg = GETREG(eregs->esp_intrpt);
esp_print_ireg(esp->ireg);
printk(" ");
esp_print_statreg(esp->sreg);
@@ -2931,10 +2946,11 @@ static inline int check_multibyte_msg(struct NCR_ESP *esp,
esp->config3[SCptr->target] |= bit;
else
esp->config3[SCptr->target] &= ~bit;
- eregs->esp_cfg3 = esp->config3[SCptr->target];
+ SETREG(eregs->esp_cfg3,
+ esp->config3[SCptr->target]);
}
- eregs->esp_soff = SDptr->sync_min_period;
- eregs->esp_stp = SDptr->sync_max_offset;
+ SETREG(eregs->esp_soff, SDptr->sync_min_period);
+ SETREG(eregs->esp_stp, SDptr->sync_max_offset);
ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
SDptr->sync_max_offset,
@@ -2949,15 +2965,16 @@ static inline int check_multibyte_msg(struct NCR_ESP *esp,
ESPSDTR(("unaccaptable sync nego, forcing async\n"));
SDptr->sync_max_offset = 0;
SDptr->sync_min_period = 0;
- eregs->esp_soff = 0;
- eregs->esp_stp = 0;
+ SETREG(eregs->esp_soff, 0);
+ SETREG(eregs->esp_stp, 0);
if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) {
if((esp->erev == fas100a) || (esp->erev == fashme))
bit = ESP_CONFIG3_FAST;
else
bit = ESP_CONFIG3_FSCSI;
esp->config3[SCptr->target] &= ~bit;
- eregs->esp_cfg3 = esp->config3[SCptr->target];
+ SETREG(eregs->esp_cfg3,
+ esp->config3[SCptr->target]);
}
}
@@ -3007,7 +3024,7 @@ static inline int check_multibyte_msg(struct NCR_ESP *esp,
/* Pure paranoia. */
esp->config3[SCptr->target] &= ~(ESP_CONFIG3_EWIDE);
}
- eregs->esp_cfg3 = esp->config3[SCptr->target];
+ SETREG(eregs->esp_cfg3, esp->config3[SCptr->target]);
/* Regardless, next try for sync transfers. */
build_sync_nego_msg(esp, esp->sync_defp, 15);
@@ -3038,7 +3055,8 @@ static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs)
message_out = MSG_PARITY_ERROR;
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
} else if(esp->erev != fashme &&
- (it = (eregs->esp_fflags & ESP_FF_FBYTES))!=1) {
+ (it = (GETREG(eregs->esp_fflags)
+ & ESP_FF_FBYTES))!=1) {
/* We certainly dropped the ball somewhere. */
message_out = INITIATOR_ERROR;
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
@@ -3046,7 +3064,7 @@ static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(esp->erev == fashme)
it = esp->hme_fifo_workaround_buffer[0];
else
- it = eregs->esp_fdata;
+ it = GETREG(eregs->esp_fdata);
esp_advance_phase(SCptr, in_msgincont);
} else {
/* it is ok and we want it */
@@ -3055,7 +3073,7 @@ static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs)
esp->hme_fifo_workaround_buffer[0];
else
it = esp->cur_msgin[esp->msgin_ctr] =
- eregs->esp_fdata;
+ GETREG(eregs->esp_fdata);
esp->msgin_ctr++;
}
} else {
@@ -3096,7 +3114,7 @@ static int esp_do_msgindone(struct NCR_ESP *esp, struct ESP_regs *eregs)
esp_advance_phase(SCptr, in_the_dark);
esp->msgin_len = 0;
}
- esp->sreg = eregs->esp_status;
+ esp->sreg = GETREG(eregs->esp_status);
esp->sreg &= ~(ESP_STAT_INTR);
if((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD))
esp_cmd(esp, eregs, ESP_CMD_MOK);
@@ -3123,7 +3141,7 @@ static int esp_do_cmdbegin(struct NCR_ESP *esp, struct ESP_regs *eregs)
esp->dma_init_write(esp, esp->esp_command_dvma, i);
} else {
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
- eregs->esp_fdata = *esp->esp_scmdp++;
+ SETREG(eregs->esp_fdata, *esp->esp_scmdp++);
esp->esp_scmdleft--;
esp_cmd(esp, eregs, ESP_CMD_TI);
}
@@ -3154,14 +3172,14 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(esp->erev == fashme)
hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
else
- eregs->esp_fdata = esp->cur_msgout[0];
+ SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
esp_cmd(esp, eregs, ESP_CMD_TI);
break;
case 2:
if(esp->do_pio_cmds){
- eregs->esp_fdata = esp->cur_msgout[0];
- eregs->esp_fdata = esp->cur_msgout[1];
+ SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
esp_cmd(esp, eregs, ESP_CMD_TI);
} else {
esp->esp_command[0] = esp->cur_msgout[0];
@@ -3180,10 +3198,10 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs)
case 4:
esp->snip = 1;
if(esp->do_pio_cmds){
- eregs->esp_fdata = esp->cur_msgout[0];
- eregs->esp_fdata = esp->cur_msgout[1];
- eregs->esp_fdata = esp->cur_msgout[2];
- eregs->esp_fdata = esp->cur_msgout[3];
+ SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[2]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[3]);
esp_cmd(esp, eregs, ESP_CMD_TI);
} else {
esp->esp_command[0] = esp->cur_msgout[0];
@@ -3204,18 +3222,18 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs)
case 5:
esp->snip = 1;
if(esp->do_pio_cmds){
- eregs->esp_fdata = esp->cur_msgout[0];
- eregs->esp_fdata = esp->cur_msgout[1];
- eregs->esp_fdata = esp->cur_msgout[2];
- eregs->esp_fdata = esp->cur_msgout[3];
- eregs->esp_fdata = esp->cur_msgout[4];
+ SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[2]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[3]);
+ SETREG(eregs->esp_fdata, esp->cur_msgout[4]);
esp_cmd(esp, eregs, ESP_CMD_TI);
} else {
- esp->esp_command[0] = esp->cur_msgout[0];
- esp->esp_command[1] = esp->cur_msgout[1];
- esp->esp_command[2] = esp->cur_msgout[2];
- esp->esp_command[3] = esp->cur_msgout[3];
- esp->esp_command[4] = esp->cur_msgout[4];
+ SETREG(esp->esp_command[0], esp->cur_msgout[0]);
+ SETREG(esp->esp_command[1], esp->cur_msgout[1]);
+ SETREG(esp->esp_command[2], esp->cur_msgout[2]);
+ SETREG(esp->esp_command[3], esp->cur_msgout[3]);
+ SETREG(esp->esp_command[4], esp->cur_msgout[4]);
if(esp->erev == fashme) {
hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5);
esp_cmd(esp, eregs, ESP_CMD_TI);
@@ -3234,7 +3252,7 @@ static int esp_do_msgout(struct NCR_ESP *esp, struct ESP_regs *eregs)
if(esp->erev == fashme) {
hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
} else {
- eregs->esp_fdata = esp->cur_msgout[0];
+ SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
}
esp->msgout_len = 1;
esp_cmd(esp, eregs, ESP_CMD_TI);
@@ -3383,11 +3401,11 @@ inline void esp_handle(struct NCR_ESP *esp)
esp->dma_irq_entry(esp);
/* Check for errors. */
- esp->sreg = eregs->esp_status;
+ esp->sreg = GETREG(eregs->esp_status);
esp->sreg &= (~ESP_STAT_INTR);
if(esp->erev == fashme) {
- esp->sreg2 = eregs->esp_status2;
- esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS);
+ esp->sreg2 = GETREG(eregs->esp_status2);
+ esp->seqreg = (GETREG(eregs->esp_sstep) & ESP_STEP_VBITS);
}
if(esp->sreg & (ESP_STAT_SPAM)) {
/* Gross error, could be due to one of:
@@ -3461,7 +3479,7 @@ inline void esp_handle(struct NCR_ESP *esp)
}
}
- esp->ireg = eregs->esp_intrpt; /* Unlatch intr and stat regs */
+ esp->ireg = GETREG(eregs->esp_intrpt); /* Unlatch intr and stat regs */
/* This cannot be done until this very moment. -DaveM */
synchronize_irq();
@@ -3674,7 +3692,7 @@ repeat:
}
#else
/* For SMP we only service one ESP on the list list at our IRQ level! */
-static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
{
struct NCR_ESP *esp;
diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h
index 4d2a78717..175b6552a 100644
--- a/drivers/scsi/NCR53C9x.h
+++ b/drivers/scsi/NCR53C9x.h
@@ -1,4 +1,4 @@
-/* NCR53C9x.c: Defines and structures for the NCR53C9x generic driver.
+/* NCR53C9x.h: Defines and structures for the NCR53C9x generic driver.
*
* Originaly esp.h: Defines and structures for the Sparc ESP
* (Enhanced SCSI Processor) driver under Linux.
@@ -6,6 +6,8 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*
* Generalization by Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * More generalization (for i386 stuff) by Tymm Twillman (tymm@computer.org)
*/
#ifndef NCR53C9X_H
@@ -131,6 +133,15 @@
/* All the ESP registers are one byte each and are accessed longwords
* apart with a big-endian ordering to the bytes.
*/
+
+/*
+ * On intel, we must use inb() and outb() for register access, and the registers
+ * are consecutive; no padding.
+ */
+
+#ifndef __i386__
+#define SETREG(reg, val) (reg = val)
+#define GETREG(reg) (reg)
struct ESP_regs {
/* Access Description Offset */
@@ -140,7 +151,7 @@ struct ESP_regs {
EREGS_PAD(fdpad);
volatile unchar esp_fdata; /* rw FIFO data bits 0x08 */
EREGS_PAD(cbpad);
- volatile unchar esp_cmd; /* rw SCSI command bits 0x0c */
+ volatile unchar esp_cmnd; /* rw SCSI command bits 0x0c */
EREGS_PAD(stpad);
volatile unchar esp_status; /* ro ESP status register 0x10 */
#define esp_busid esp_status /* wo Bus ID for select/reselect 0x10 */
@@ -178,6 +189,52 @@ struct ESP_regs {
#define fas_rhi esp_fgrnd /* rw HME extended counter 0x3c */
};
+#else
+#define SETREG(reg, val) outb(val, reg)
+#define GETREG(reg) inb(reg)
+
+struct ESP_regs {
+#ifdef CONFIG_MCA
+ unsigned int slot;
+#endif
+ unsigned int io_addr;
+ /* Access Description Offset */
+#define esp_tclow io_addr /* rw Low bits of the transfer count 0x00 */
+#define esp_tcmed io_addr + 1 /* rw Mid bits of the transfer count 0x04 */
+#define esp_fdata io_addr + 2 /* rw FIFO data bits 0x08 */
+#define esp_cmnd io_addr + 3 /* rw SCSI command bits 0x0c */
+#define esp_status io_addr + 4 /* ro ESP status register 0x10 */
+#define esp_busid esp_status /* wo Bus ID for select/reselect 0x10 */
+#define esp_intrpt io_addr + 5 /* ro Kind of interrupt 0x14 */
+#define esp_timeo esp_intrpt /* wo Timeout value for select/resel 0x14 */
+#define esp_sstep io_addr + 6 /* ro Sequence step register 0x18 */
+#define esp_stp esp_sstep /* wo Transfer period per sync 0x18 */
+#define esp_fflags io_addr + 7 /* ro Bits of current FIFO info 0x1c */
+#define esp_soff esp_fflags /* wo Sync offset 0x1c */
+#define esp_cfg1 io_addr + 8 /* rw First configuration register 0x20 */
+#define esp_cfact io_addr + 9 /* wo Clock conversion factor 0x24 */
+#define esp_status2 esp_cfact /* ro HME status2 register 0x24 */
+#define esp_ctest io_addr + 10 /* wo Chip test register 0x28 */
+#define esp_cfg2 io_addr + 11 /* rw Second configuration register 0x2c */
+
+ /* The following is only found on the 53C9X series SCSI chips */
+#define esp_cfg3 io_addr + 12 /* rw Third configuration register 0x30 */
+#define esp_hole io_addr + 13 /* hole in register map 0x34 */
+
+ /* The following is found on all chips except the NCR53C90 (ESP100) */
+#define esp_tchi io_addr + 14 /* rw High bits of transfer count 0x38 */
+#define esp_uid esp_tchi /* ro Unique ID code 0x38 */
+#define fas_rlo esp_tchi /* rw HME extended counter 0x38 */
+#define esp_fgrnd io_addr + 15 /* rw Data base for fifo 0x3c */
+#define fas_rhi esp_fgrnd /* rw HME extended counter 0x3c */
+};
+
+#ifndef save_and_cli
+#define save_and_cli(flags) save_flags(flags); cli();
+#endif
+
+#endif
+
/* Various revisions of the ESP board. */
enum esp_rev {
esp100 = 0x00, /* NCR53C90 - very broken */
@@ -195,7 +252,11 @@ enum esp_rev {
struct NCR_ESP {
struct NCR_ESP *next; /* Next ESP on probed or NULL */
struct ESP_regs *eregs; /* All esp registers */
+#ifndef __i386__
struct Linux_DMA *dma; /* Who I do transfers with. */
+#else
+ int dma;
+#endif
void *dregs; /* And his registers. */
struct Scsi_Host *ehost; /* Backpointer to SCSI Host */
@@ -273,6 +334,10 @@ struct NCR_ESP {
int diff; /* Differential SCSI bus? */
int bursts; /* Burst sizes our DVMA supports */
+#ifdef CONFIG_MCA
+ int slot; /* MCA slot the adapter occupies */
+#endif
+
/* Our command queues, only one cmd lives in the current_SC queue. */
Scsi_Cmnd *issue_SC; /* Commands to be issued */
Scsi_Cmnd *current_SC; /* Who is currently working the bus */
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index 554863080..e13d8a632 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -656,10 +656,10 @@ static void internal_done(Scsi_Cmnd *SCpnt) {
static void wait_intr() {
int i = jiffies + WATCHDOG;
- while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */
+ while(time_after(i,jiffies) && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */
barrier();
- if (i <= jiffies) { /* Timed out */
+ if (time_before_eq(i,jiffies)) { /* Timed out */
rtrc(0);
current_SC->result = DID_TIME_OUT << 16;
current_SC->SCp.phase = idle;
@@ -983,9 +983,9 @@ static int irq_probe()
/* Wait for the interrupt to occur */
i = jiffies + WATCHDOG;
- while(i > jiffies && !(inb(STAT_REG) & 0x80))
+ while(time_after(i, jiffies) && !(inb(STAT_REG) & 0x80))
barrier();
- if (i <= jiffies) { /* Timed out, must be hardware trouble */
+ if (time_before_eq(i, jiffies)) { /* Timed out, must be hardware trouble */
probe_irq_off(irqs);
return -1;
}
diff --git a/drivers/scsi/README.aic7xxx b/drivers/scsi/README.aic7xxx
index b350d9d58..bbeeeb2f6 100644
--- a/drivers/scsi/README.aic7xxx
+++ b/drivers/scsi/README.aic7xxx
@@ -37,8 +37,10 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
AHA-3940U
AHA-3940W
AHA-3940UW
+ AHA-3940AUW
AHA-3940U2W
AHA-3950U2B
+ AHA-3950U2D
AHA-3985
AHA-3985U
AHA-3985W
@@ -52,6 +54,7 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
AIC-787x
AIC-788x
AIC-789x
+ AIC-3860
Bus Types
----------------------------
@@ -69,8 +72,30 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
AHA-398x - PCI RAID controllers with three separate SCSI controllers
on-board.
- NOTE: The AHA-2920 is NOT an AIC-7xxx based controller, and is not
- handled by this driver.
+ Not Supported Devices
+ ------------------------------
+ Adaptec Cards
+ ----------------------------
+ AHA-2920 (Only the cards that use the Future Domain chipset are not
+ supported, any 2920 cards based on Adaptec AIC chipsets are
+ supported)
+ AAA-13x Raid Adapters
+ AAA-113x Raid Port Card
+
+ Motherboard Chipsets
+ ----------------------------
+ AIC-7810
+
+ Bus Types
+ ----------------------------
+ R - Raid Port busses are not supported.
+
+ The hardware RAID devices sold by Adaptec are *NOT* supported by this
+ driver (and will people please stop emailing me about them, they are
+ a totally separate beast from the bare SCSI controllers and this driver
+ can not be retrofitted in any sane manner to support the hardware RAID
+ features on those cards - Doug Ledford).
+
People
------------------------------
@@ -299,13 +324,12 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
binary->hex conversion then send an email to the aic7xxx mailing
list and someone can help you out.
- "aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to enable
- tagged queueing on specific devices. As of driver version 5.0.6, we
- now globally enable tagged queueing by default, but we also disable
- tagged queueing on all individual devices by default. In order to
- enable tagged queueing for certian devices at boot time, a user may
+ "aic7xxx=tag_info:{{8,8..},{8,8..},..}" - This option is used to disable
+ tagged queueing on specific devices. As of driver version 5.1.8, we
+ now globally enable tagged queueing by default. In order to
+ disable tagged queueing for certian devices at boot time, a user may
use this boot param. The driver will then parse this message out
- and enable the specific device entries that are present based upon
+ and disable the specific device entries that are present based upon
the value given. The param line is parsed in the following manner:
{ - first instance indicates the start of this parameter values
@@ -337,18 +361,13 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
commas with no value specified will simply increment to the next id
without changing anything for the missing values.
- tag_info:{{8,8},,{8,8}}
- First adapter, scsi id 0 to 8, id 1 to 8, remainder stay at their
- default. Second adapter stays entirely at default. Third
- adapter, id 0 to 8, id 1 to 8, remainder at default (identical to
- first adapter).
-
- tag_info:{,,,{,,,64}}
+ tag_info:{,,,{,,,255}}
First, second, and third adapters at default values. Fourth
- adapter, id 3 to 64. Notice that leading commas simply increment
- what the first number effects, and there are no need for trailing
- commas. When you close out an adapter, or the entire entry,
- anything not explicitly set stays at the default value.
+ adapter, id 3 is disabled. Notice that leading commas simply
+ increment what the first number effects, and there are no need
+ for trailing commas. When you close out an adapter, or the
+ entire entry, anything not explicitly set stays at the default
+ value.
A final note on this option. The scanner I used for this isn't
perfect or highly robust. If you mess the line up, the worst that
@@ -449,10 +468,16 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
ftp://ekf2.vsb.cz/pub/linux/kernel/aic7xxx/ftp.teleport.com/
- European Linux mirror of Teleport site
+ Web sites
+ ------------------------------
+ http://developer.redhat.com/aic7xxx/
+ - Primary web site maintained by Doug Ledford. I haven't actually
+ put anything up yet....but I'm planning on it. This information
+ is put here as an add for the vapor page :)
Dean W. Gehnert
deang@teleport.com
$Revision: 3.0 $
-Modified by Doug Ledford 1998
+Modified by Doug Ledford 1998-9
diff --git a/drivers/scsi/README.ncr53c8xx b/drivers/scsi/README.ncr53c8xx
index 409967d0e..47bbe19ba 100644
--- a/drivers/scsi/README.ncr53c8xx
+++ b/drivers/scsi/README.ncr53c8xx
@@ -33,7 +33,7 @@ Written by Gerard Roudier <groudier@club-internet.fr>
10.6 SCSI BUS checking boot option
11. Some constants and flags of the ncr53c8xx.h header file
12. Installation
-13. Architecture dependant features
+13. Architecture dependent features
14. Known problems
14.1 Tagged commands with Iomega Jaz device
14.2 Device names change when another controller is added
@@ -948,7 +948,7 @@ patches:
ftp://ftp.tux.org/pub/people/gerard-roudier/README
-13. Architecture dependant features.
+13. Architecture dependent features.
<Not yet written>
diff --git a/drivers/scsi/README.tmscsim b/drivers/scsi/README.tmscsim
index b11cd4df2..99ae1e5a7 100644
--- a/drivers/scsi/README.tmscsim
+++ b/drivers/scsi/README.tmscsim
@@ -17,6 +17,7 @@ The tmscsim driver supports PCI SCSI Host Adapters based on the AM53C974
chip. AM53C974 based SCSI adapters include:
Tekram DC390, DC390T
Dawicontrol 2974
+ QLogic Fast! PCI Basic
some on-board adapters
(This is most probably not a complete list)
@@ -44,7 +45,8 @@ The numbering scheme isn't consistent. The first versions went from 1.00 to
1.12, then 1.20a to 1.20t. Finally I decided to use the ncr53c8xx scheme. So
the next revisions will be 2.0a to 2.0X (stable), 2.1a to 2.1X (experimental),
2.2a to 2.2X (stable, again) etc. (X = anything between a and z.) If I send
-fixes to people for testing, those will have a digit appended, e.g. 2.0a1.
+fixes to people for testing, I create intermediate versions with a digit
+appended, e.g. 2.0c3.
2. Installation
@@ -55,32 +57,36 @@ driver. Of course you have to choose to compile SCSI support and DC390(T)
support into your kernel or as module when configuring your kernel for
compiling.
-If you got an older kernel with an old version of this driver included, you
-should copy the files (dc390.h, tmscsim.h, tmscsim.c, scsiiom.c and
-README.tmscsim) from this directory to linux/drivers/scsi. You have to
-recompile your kernel/module of course.
+ If you got an old kernel (pre 2.1.127, pre 2.0.37p1) with an old version of
+ this driver: Get dc390-21125-20b.diff.gz or dc390-2036p21-20b1.diff.gz from
+ my website and apply the patch.
-You should apply the three patches included in dc390-20-kernel.diff
-(Applying them: cd /usr/src; patch -p0 <~/dc390-20-kernel.diff)
-The patches are against 2.1.103, so you might have to manually resolve
-rejections when applying to another kernel version.
+ If you want to do it manually, you should copy the files (dc390.h,
+ tmscsim.h, tmscsim.c, scsiiom.c and README.tmscsim) from this directory to
+ linux/drivers/scsi. You have to recompile your kernel/module of course.
-The patches will update the kernel startup code to allow boot parameters to
-be passed to the driver, update the Documentation and finally offer you the
-possibility to omit the non-DC390 parts of the driver.
-(By selecting "Omit support for non DC390" you basically disable the
-emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes
-of memory.)
+ You should apply the three patches included in dc390-120-kernel.diff
+ (Applying them: cd /usr/src; patch -p0 <~/dc390-120-kernel.diff)
+ The patches are against 2.1.125, so you might have to manually resolve
+ rejections when applying to another kernel version.
+
+ The patches will update the kernel startup code to allow boot parameters to
+ be passed to the driver, update the Documentation and finally offer you the
+ possibility to omit the non-DC390 parts of the driver.
+ (By selecting "Omit support for non DC390" you basically disable the
+ emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes
+ of memory.)
If you got a very old kernel without the tmscsim driver (pre 2.0.31)
I recommend upgrading your kernel. However, if you don't want to, please
contact me to get the appropriate patches.
-Testing a SCSI driver is always a delicate thing to do. The 2.0 driver has
+
+Upgrading a SCSI driver is always a delicate thing to do. The 2.0 driver has
proven stable on many systems, but it's still a good idea to take some
precautions. In an ideal world you would have a full backup of your disks.
The world isn't ideal and most people don't have full backups (me neither).
-So take at least the following two measures:
+So take at least the following measures:
* make your kernel remount the FS read-only on detecting an error:
tune2fs -e remount-ro /dev/sd??
* have copies of your SCSI disk's partition tables on some safe location:
@@ -103,18 +109,19 @@ SA_SHIRQ | SA_INTERRUPT.
3.Features
----------
- SCSI
- * Tagged queueing
+ * Tagged command queueing
* Sync speed up to 10 MHz
* Disconnection
* Multiple LUNs
- General / Linux interface
- * Support for up to 4 adapters.
+ * Support for up to 4 AM53C974 adapters.
* DC390 EEPROM usage or boot/module params
* Information via cat /proc/scsi/tmscsim/?
* Dynamically configurable by writing to /proc/scsi/tmscsim/?
* Dynamic allocation of resources
- * SMP support: Adapter specific locks (Linux 2.1.x)
+ * SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter
+ specific locks (Linux 2.3)
* Uniform source code for Linux-2.x.y
* Support for dyn. addition/removal of devices via add/remove-single-device
(Try: echo "scsi add-single-device H C I L" >/proc/scsi/scsi
@@ -336,9 +343,7 @@ to further improve its usability:
Further investigation on these problems:
-* TagQ and Disconnection (Resel: SRB Tag Seleection)
-* Problems with IRQ sharing (IO-APIC on SMP Systems) (??)
-* Driver crashes with readcdda (xcdroast)
+* Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error)
Known problems:
@@ -362,12 +367,9 @@ Known problems:
Richard Waltham <dormouse@farsrobt.demon.co.uk> or Doug Ledford
<dledford@dialnet.net>, if you want to help further debugging it.
* 2.0.35: CD changers (e.g. NAKAMICHI MBR-7.{0,2}) have problems because
- the mid-level code doesn't handle BLIST_SINGLELUN correctly. Apply
- the patch 2035-scsi-singlelun.diff. Thanks to Chiaki Ishikawa.
- I was told that this fix will be in 2.0.36, so you don't need it for
- 2.0.36.
-[The patch file is contained in the dc390-XXX.tar.gz files which can be found
-on the ftp server. See below.]
+ the mid-level code doesn't handle BLIST_SINGLELUN correctly. There used
+ to be a patch included here to fix this, but I was told that it is fixed
+ in 2.0.36.
7. Bug reports, debugging and updates
@@ -379,7 +381,7 @@ If you find something, which you believe to be a bug, please report it to me.
Please append the output of /proc/scsi/scsi, /proc/scsi/tmscsim/? and
maybe the DC390 log messages to the report.
-Bug reports should be send to me (Kurt Garloff <K.Garloff@ping.de>) as well
+Bug reports should be send to me (Kurt Garloff <dc390@garloff.de>) as well
as to the linux-scsi list (<linux-scsi@vger.rutgers.edu>), as sometimes bugs
are caused by the SCSI mid-level code.
@@ -391,7 +393,10 @@ AM53C974, the logging might produce log output again, and you might end
having your box spending most of its time doing the logging.
The latest version of the driver can be found at:
-ftp://student.physik.uni-dortmund.de/pub/linux/kernel/dc390/
+ http://www.garloff.de/kurt/linux/dc390/
+and
+ ftp://student.physik.uni-dortmund.de/pub/linux/kernel/dc390/
+(The latter might shut down some day.)
8. Acknowledgements
@@ -408,6 +413,6 @@ doing this during early revisions).
-------------------------------------------------------------------------
-Written by Kurt Garloff <K.Garloff@ping.de> 1998/06/11
-Last updated 1998/10/15, driver revision 2.0b
-$Id: README.tmscsim,v 2.4 1998/10/24 08:45:02 garloff Exp $
+Written by Kurt Garloff <kurt@garloff.de> 1998/06/11
+Last updated 1998/12/25, driver revision 2.0d
+$Id: README.tmscsim,v 2.9 1998/12/25 18:04:20 garloff Exp $
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 10fae9bbd..dc46aa27e 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -3941,6 +3941,8 @@ int
advansys_proc_info(char *buffer, char **start, off_t offset, int length,
int hostno, int inout)
{
+#ifdef CONFIG_PROC_FS
+
struct Scsi_Host *shp;
asc_board_t *boardp;
int i;
@@ -4147,9 +4149,12 @@ advansys_proc_info(char *buffer, char **start, off_t offset, int length,
ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt);
return totcnt;
+#else /* CONFIG_PROC_FS */
+ return 0;
+#endif /* CONFIG_PROC_FS */
+
}
#endif /* version >= v1.3.0 */
-
/*
* advansys_detect()
*
@@ -5785,8 +5790,8 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
}
scp->result = HOST_BYTE(DID_ERROR);
ret = SCSI_RESET_ERROR;
- } else if (jiffies >= boardp->last_reset &&
- jiffies < (boardp->last_reset + (10 * HZ))) {
+ } else if (time_after_eq(jiffies, boardp->last_reset) &&
+ time_before(jiffies, boardp->last_reset + (10 * HZ))) {
/*
* Don't allow a reset to be attempted within 10 seconds
* of the last reset.
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 0d16c2876..70d233f37 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -247,7 +247,7 @@
C/H/S addressing.
The number of cylinders/heads/sectors is called geometry and is required
- as base for requests in C/H/S adressing. SCSI only knows about the
+ as base for requests in C/H/S addressing. SCSI only knows about the
total capacity of disks in blocks (sectors).
Therefore the SCSI BIOS/DOS driver has to calculate a logical/virtual
@@ -276,7 +276,7 @@
extended translation. This means that the BIOS uses 255 for heads,
63 for sectors and then divides the capacity of the disk by 255*63
(about 8 MB), as soon it sees a disk greater than 1 GB. That results
- in a maximum of about 8 GB adressable diskspace in the partition table
+ in a maximum of about 8 GB addressable diskspace in the partition table
(but there are already bigger disks out there today).
To make it even more complicated the translation mode might/might
@@ -566,6 +566,7 @@ static struct signature {
{ "Adaptec BIOS:AVA-282X", 0xc, 21 }, /* Adaptec 282x */
{ "Adaptec IBM Dock II SCSI", 0x2edd, 24 }, /* IBM Thinkpad Dock II */
{ "Adaptec BIOS:AHA-1532P", 0x1c, 22 }, /* IBM Thinkpad Dock II SCSI */
+ { "DTC3520A Host Adapter BIOS", 0x318a, 26 }, /* DTC 3520A ISA SCSI */
};
#define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
#endif
@@ -575,7 +576,7 @@ static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */
{
unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
- while (jiffies < the_time)
+ while (time_before(jiffies, the_time))
barrier();
}
@@ -1038,7 +1039,7 @@ int aha152x_detect(Scsi_Host_Template * tpnt)
SETBITS(DMACNTRL0, SWINT);
the_time=jiffies+100;
- while(!HOSTDATA(shpnt)->swint && jiffies<the_time)
+ while(!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time))
barrier();
free_irq(shpnt->irq,shpnt);
diff --git a/drivers/scsi/aic7xxx.c b/drivers/scsi/aic7xxx.c
index 078b64ae6..e5907b67a 100644
--- a/drivers/scsi/aic7xxx.c
+++ b/drivers/scsi/aic7xxx.c
@@ -100,7 +100,7 @@
*
* Further driver modifications made by Doug Ledford <dledford@redhat.com>
*
- * Copyright (c) 1997-1998 Doug Ledford
+ * Copyright (c) 1997-1999 Doug Ledford
*
* These changes are released under the same licensing terms as the FreeBSD
* driver written by Justin Gibbs. Please see his Copyright notice above
@@ -354,7 +354,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
-#define AIC7XXX_C_VERSION "5.1.4"
+#define AIC7XXX_C_VERSION "5.1.10"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -449,6 +449,8 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
*/
#ifdef CONFIG_AIC7XXX_CMDS_PER_LUN
#define AIC7XXX_CMDS_PER_LUN CONFIG_AIC7XXX_CMDS_PER_LUN
+#else
+#define AIC7XXX_CMDS_PER_LUN 24
#endif
/* Set this to the delay in seconds after SCSI bus reset. */
@@ -579,7 +581,9 @@ static const char *board_names[] = {
"Adaptec AIC-7890/1 Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AHA-294X Ultra2 SCSI host adapter", /* AIC_7890 */
"Adaptec AIC-7896/7 Ultra2 SCSI host adapter", /* AIC_7896 */
- "Adaptec AHA-394X Ultra2 SCSI host adapter" /* AIC_7897 */
+ "Adaptec AHA-394X Ultra2 SCSI host adapter", /* AIC_7897 */
+ "Adaptec AHA-395X Ultra2 SCSI host adapter", /* AIC_7897 */
+ "Adaptec PCMCIA SCSI controller", /* card bus stuff */
};
/*
@@ -882,6 +886,7 @@ typedef enum {
* and what flags weren't. This way, I could clean up the flag usage on
* a use by use basis. Doug Ledford
*/
+ AHC_RESET_DELAY = 0x00080000,
AHC_A_SCANNED = 0x00100000,
AHC_B_SCANNED = 0x00200000,
AHC_MULTI_CHANNEL = 0x00400000,
@@ -941,7 +946,6 @@ struct aic7xxx_scb {
struct aic7xxx_scb *q_next; /* next scb in queue */
volatile scb_flag_type flags; /* current state of scb */
struct hw_scatterlist *sg_list; /* SG list in adapter format */
- void *kmalloc_ptr;
unsigned char tag_action;
unsigned char sg_count;
unsigned char sense_cmd[6]; /*
@@ -952,6 +956,7 @@ struct aic7xxx_scb {
* don't have to calculate anything
* during underflow/overflow/stat code
*/
+ void *kmalloc_ptr;
};
/*
@@ -1029,88 +1034,73 @@ struct aic7xxx_host {
* This is the first 64 bytes in the host struct
*/
- struct Scsi_Host *host; /* pointer to scsi host */
- struct aic7xxx_host *next; /* allow for multiple IRQs */
- int host_no; /* SCSI host number */
- unsigned long base; /* card base address */
- volatile unsigned char *maddr; /* memory mapped address */
- unsigned long mbase; /* I/O memory address */
+ /*
+ * We are grouping things here....first, items that get either read or
+ * written with nearly every interrupt
+ */
volatile ahc_flag_type flags;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
- spinlock_t spin_lock;
-#endif
- volatile unsigned char cpu_lock_count[NR_CPUS];
- ahc_chip chip; /* chip type */
ahc_feature features; /* chip features */
- unsigned long last_reset;
+ unsigned long base; /* card base address */
+ volatile unsigned char *maddr; /* memory mapped address */
unsigned long isr_count; /* Interrupt count */
unsigned long spurious_int;
- struct target_cmd *targetcmds;
- unsigned int num_targetcmds;
+ scb_data_type *scb_data;
+ volatile unsigned short needsdtr;
+ volatile unsigned short sdtr_pending;
+ volatile unsigned short needwdtr;
+ volatile unsigned short wdtr_pending;
+ struct aic7xxx_cmd_queue {
+ Scsi_Cmnd *head;
+ Scsi_Cmnd *tail;
+ } completeq;
+
+ /*
+ * Things read/written on nearly every entry into aic7xxx_queue()
+ */
+ volatile scb_queue_type waiting_scbs;
unsigned short discenable; /* Targets allowed to disconnect */
unsigned short tagenable; /* Targets using tagged I/O */
unsigned short orderedtag; /* Ordered Q tags allowed */
- volatile unsigned char activescbs; /* active scbs */
- volatile unsigned char max_activescbs;
unsigned char unpause; /* unpause value for HCNTRL */
unsigned char pause; /* pause value for HCNTRL */
volatile unsigned char qoutfifonext;
+ volatile unsigned char activescbs; /* active scbs */
+ volatile unsigned char max_activescbs;
volatile unsigned char qinfifonext;
- /*
- * MAX_TARGETS is currently == 16, so that makes these entries the next
- * 64 bytes
- */
-
#define DEVICE_PRESENT 0x01
#define BUS_DEVICE_RESET_PENDING 0x02
-#define DEVICE_TIMEOUT 0x04
+#define DEVICE_RESET_DELAY 0x04
#define DEVICE_PRINT_SDTR 0x08
#define DEVICE_PRINT_WDTR 0x10
-#define DEVICE_SUCCESS 0x20
-#define DEVICE_TAGGED_SUCCESS 0x40
+#define DEVICE_WAS_BUSY 0x20
#define DEVICE_SCANNED 0x80
volatile unsigned char dev_flags[MAX_TARGETS];
volatile unsigned char dev_active_cmds[MAX_TARGETS];
volatile unsigned char dev_temp_queue_depth[MAX_TARGETS];
unsigned char dev_commands_sent[MAX_TARGETS];
- /*
- * The next 128 (or 256 on 64 bit machines)....
- */
- Scsi_Cmnd *dev_wdtr_cmnd[MAX_TARGETS];
- Scsi_Cmnd *dev_sdtr_cmnd[MAX_TARGETS];
+ unsigned int dev_timer_active; /* Which devs have a timer set */
+ struct timer_list dev_timer;
+ unsigned long dev_expires[MAX_TARGETS];
- /*
- * The next 64....
- */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+ spinlock_t spin_lock;
+ volatile unsigned char cpu_lock_count[NR_CPUS];
+#endif
- long dev_last_reset[MAX_TARGETS];
- /*
- * The next 64....
- */
+#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
+ Scsi_Cmnd *dev_wdtr_cmnd[MAX_TARGETS];
+ Scsi_Cmnd *dev_sdtr_cmnd[MAX_TARGETS];
+#endif
- unsigned char dev_mid_level_queue_depth[MAX_TARGETS];
unsigned char dev_last_queue_full[MAX_TARGETS];
unsigned char dev_last_queue_full_count[MAX_TARGETS];
unsigned char dev_max_queue_depth[MAX_TARGETS];
- /*
- * The next 128....
- */
-
volatile scb_queue_type delayed_scbs[MAX_TARGETS];
- /*
- *
- */
-
- struct timer_list dev_timer[MAX_TARGETS];
-
- /*
- * The next 64....
- */
unsigned char msg_buf[9]; /* The message for the target */
unsigned char msg_type;
@@ -1120,16 +1110,6 @@ struct aic7xxx_host {
unsigned char msg_len; /* Length of message */
unsigned char msg_index; /* Index into msg_buf array */
transinfo_type transinfo[MAX_TARGETS];
- volatile scb_queue_type waiting_scbs; /*
- * SCBs waiting for space in
- * the QINFIFO.
- */
- scb_data_type *scb_data;
-
- struct aic7xxx_cmd_queue {
- Scsi_Cmnd *head;
- Scsi_Cmnd *tail;
- } completeq;
/*
@@ -1147,16 +1127,11 @@ struct aic7xxx_host {
volatile unsigned char qoutfifo[256];
volatile unsigned char qinfifo[256];
unsigned int irq; /* IRQ for this adapter */
- volatile unsigned short needsdtr;
- volatile unsigned short sdtr_pending;
- volatile unsigned short needwdtr;
- volatile unsigned short wdtr_pending;
int instance; /* aic7xxx instance number */
int scsi_id; /* host adapter SCSI ID */
int scsi_id_b; /* channel B for twin adapters */
unsigned int bios_address;
int board_name_index;
- unsigned long reset_start;
unsigned short needsdtr_copy; /* default config */
unsigned short needwdtr_copy; /* default config */
unsigned short ultraenb; /* Ultra mode target list */
@@ -1170,6 +1145,11 @@ struct aic7xxx_host {
struct seeprom_config sc;
unsigned short sc_type;
unsigned short sc_size;
+ struct aic7xxx_host *next; /* allow for multiple IRQs */
+ struct Scsi_Host *host; /* pointer to scsi host */
+ int host_no; /* SCSI host number */
+ unsigned long mbase; /* I/O memory address */
+ ahc_chip chip; /* chip type */
/*
* Statistics Kept:
@@ -1184,21 +1164,27 @@ struct aic7xxx_host {
*
* NOTE: Enabling this feature is likely to cause a noticeable performance
* decrease as the accesses into the stats structures blows apart multiple
- * cache lines and is CPU time consuming. We keep the xfer count always
- * for use by the aic7xxx_proc.c code, but only do the bins if the
- * proc stats code is enabled.
+ * cache lines and is CPU time consuming.
+ *
+ * NOTE: Since it doesn't really buy us much, but consumes *tons* of RAM
+ * and blows apart all sorts of cache lines, I modified this so that we
+ * no longer look at the LUN. All LUNs now go into the same bin on each
+ * device for stats purposes.
*/
struct aic7xxx_xferstats {
- long xfers; /* total xfer count */
- long w_total; /* total writes */
- long w_total512; /* 512 byte blocks written */
- long r_total; /* total reads */
- long r_total512; /* 512 byte blocks read */
+ long w_total; /* total writes */
+ long r_total; /* total reads */
#ifdef AIC7XXX_PROC_STATS
- long w_bins[10]; /* binned write */
- long r_bins[10]; /* binned reads */
+ long w_bins[8]; /* binned write */
+ long r_bins[8]; /* binned reads */
#endif /* AIC7XXX_PROC_STATS */
- } stats[MAX_TARGETS][MAX_LUNS]; /* [(channel << 3)|target][lun] */
+ } stats[MAX_TARGETS]; /* [(channel << 3)|target] */
+
+#if 0
+ struct target_cmd *targetcmds;
+ unsigned int num_targetcmds;
+#endif
+
};
/*
@@ -1282,11 +1268,9 @@ static unsigned int aic7xxx_no_reset = 0;
*/
static int aic7xxx_reverse_scan = 0;
/*
- * This setting enables a hack to fix the IRQ settings on buggy 7895
- * MB controller setups:
- * -1 == Disable this hack
- * 0 == Use the Channel A IRQ for both channels
- * 1 == Use the Channel B IRQ for both channels
+ * Should we force EXTENDED translation on a controller.
+ * 0 == Use whatever is in the SEEPROM or default to off
+ * 1 == Use whatever is in the SEEPROM or default to on
*/
static unsigned int aic7xxx_extended = 0;
/*
@@ -1511,6 +1495,21 @@ mdelay(int milliseconds)
for(i=0; i<milliseconds; i++)
udelay(1000);
}
+
+static inline int
+time_after_eq(unsigned long a, unsigned long b)
+{
+ return((long)((a) - (b)) >= 0L);
+}
+
+static inline int
+timer_pending(struct timer_list *timer)
+{
+ return( timer->prev != NULL );
+}
+
+#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
+
#endif
static inline unsigned char
@@ -1950,7 +1949,10 @@ aic7xxx_loadseq(struct aic7xxx_host *p)
{
printk(KERN_INFO "(scsi%d) Downloading sequencer code...", p->host_no);
}
+#if 0
download_consts[TMODE_NUMCMDS] = p->num_targetcmds;
+#endif
+ download_consts[TMODE_NUMCMDS] = 0;
cur_patch = &sequencer_patches[0];
downloaded = 0;
skip_addr = 0;
@@ -2873,6 +2875,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
char *buffer;
+ p->dev_flags[tindex] |= DEVICE_PRESENT;
if(cmd->use_sg)
{
struct scatterlist *sg;
@@ -2914,23 +2917,34 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
p->needsdtr_copy |= (1<<tindex);
if (p->flags & AHC_SEEPROM_FOUND)
+ {
p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
- else if (p->features & AHC_ULTRA2)
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
- else if (p->features & AHC_ULTRA)
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
- else
- p->transinfo[tindex].goal_period =
- aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
-
- if (p->features & AHC_ULTRA2)
- p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
- else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
- p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ p->transinfo[tindex].goal_offset = p->transinfo[tindex].user_offset;
+ }
else
- p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ {
+ if (p->features & AHC_ULTRA2)
+ {
+ p->transinfo[tindex].goal_period =
+ aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
+ }
+ else if (p->features & AHC_ULTRA)
+ {
+ p->transinfo[tindex].goal_period =
+ aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
+ }
+ else
+ {
+ p->transinfo[tindex].goal_period =
+ aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
+ }
+ if (p->features & AHC_ULTRA2)
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+ else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+ else
+ p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+ }
}
else
{
@@ -3076,12 +3090,7 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
int x;
#endif /* AIC7XXX_PROC_STATS */
- sp = &p->stats[TARGET_INDEX(cmd)][cmd->lun & 0x7];
- sp->xfers++;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if ( (sp->xfers > 16) && (aic7xxx_verbose > 0xffff) )
- aic7xxx_verbose &= 0xffff;
-#endif
+ sp = &p->stats[TARGET_INDEX(cmd)];
/*
* For block devices, cmd->request.cmd is always == either READ or
@@ -3093,7 +3102,10 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
(cmd->data_cmnd[0] == WRITE_FILEMARKS) )
{
sp->w_total++;
- sp->w_total512 += (actual >> 9);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
+ if ( (sp->w_total > 16) && (aic7xxx_verbose > 0xffff) )
+ aic7xxx_verbose &= 0xffff;
+#endif
#ifdef AIC7XXX_PROC_STATS
ptr = sp->w_bins;
#endif /* AIC7XXX_PROC_STATS */
@@ -3101,23 +3113,32 @@ aic7xxx_done(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
else
{
sp->r_total++;
- sp->r_total512 += (actual >> 9);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
+ if ( (sp->r_total > 16) && (aic7xxx_verbose > 0xffff) )
+ aic7xxx_verbose &= 0xffff;
+#endif
#ifdef AIC7XXX_PROC_STATS
ptr = sp->r_bins;
#endif /* AIC7XXX_PROC_STATS */
}
#ifdef AIC7XXX_PROC_STATS
- for (x = 9; x <= 17; x++)
+ x = -10;
+ while(actual)
{
- if (actual < (1 << x))
- {
- ptr[x - 9]++;
- break;
- }
+ actual >>= 1;
+ x++;
+ }
+ if (x < 0)
+ {
+ ptr[0]++;
}
- if (x > 17)
+ else if (x > 7)
{
- ptr[x - 9]++;
+ ptr[7]++;
+ }
+ else
+ {
+ ptr[x]++;
}
#endif /* AIC7XXX_PROC_STATS */
}
@@ -3401,39 +3422,24 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
for (i = min_target; i <= max_target; i++)
{
+ if ( i == p->scsi_id )
+ {
+ continue;
+ }
if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
printk(INFO_LEAD "Cleaning up status information "
"and delayed_scbs.\n", p->host_no, channel, i, lun);
- if ( !(p->dev_flags[i] & DEVICE_TAGGED_SUCCESS) &&
- (p->dev_active_cmds[i]) &&
- (p->tagenable & (0x01 << i)) )
- {
- printk(INFO_LEAD "Device appears to be choking on tagged commands.\n",
- p->host_no, channel, i, lun);
- printk(INFO_LEAD "Will use untagged I/O instead.\n", p->host_no,
- channel, i, lun);
- p->dev_max_queue_depth[i] = 1;
- p->dev_temp_queue_depth[i] = 1;
- p->tagenable &= ~(0x01 << i);
- p->orderedtag &= ~(0x01 << i);
- }
p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
if ( tag == SCB_LIST_NULL )
{
- p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR;
- p->dev_last_reset[i] = jiffies;
+ p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR |
+ DEVICE_RESET_DELAY;
+ p->dev_expires[i] = jiffies + (4 * HZ);
+ p->dev_timer_active |= (0x01 << i);
p->dev_last_queue_full_count[i] = 0;
p->dev_last_queue_full[i] = 0;
p->dev_temp_queue_depth[i] =
p->dev_max_queue_depth[i];
- /*
- * In case this isn't a full bus reset, we want to add a 4 second timer in
- * here so that we can delay all re-sent commands for this device for the
- * 4 seconds and then have our timer routine pick them back up.
- */
- del_timer(&p->dev_timer[i]);
- p->dev_timer[i].expires = jiffies + (4 * HZ);
- add_timer(&p->dev_timer[i]);
}
for(j=0; j<MAX_LUNS; j++)
{
@@ -3480,8 +3486,14 @@ aic7xxx_reset_device(struct aic7xxx_host *p, int target, int channel,
"delayed_scbs queue!\n", p->host_no, channel, i, lun);
scbq_init(&p->delayed_scbs[i]);
}
- if ( p->delayed_scbs[i].head == NULL )
- del_timer(&p->dev_timer[i]);
+ if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) ||
+ time_after_eq(p->dev_timer.expires, p->dev_expires[i]) )
+ {
+ del_timer(&p->dev_timer);
+ p->dev_timer.expires = p->dev_expires[i];
+ add_timer(&p->dev_timer);
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ }
}
}
@@ -3946,12 +3958,6 @@ aic7xxx_reset_channel(struct aic7xxx_host *p, int channel, int initiate_reset)
*/
aic7xxx_reset_device(p, ALL_TARGETS, channel, ALL_LUNS, SCB_LIST_NULL);
- /*
- * Convince Mid Level SCSI code to leave us be for a little bit...
- */
- p->last_reset = jiffies;
- p->host->last_reset = (jiffies + (HZ * AIC7XXX_RESET_DELAY));
-
if ( !(p->features & AHC_TWIN) )
{
restart_sequencer(p);
@@ -3993,38 +3999,18 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
tindex = TARGET_INDEX(scb->cmd);
if ( !scb->tag_action && (p->tagenable & (1<<tindex)) )
{
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- printk(INFO_LEAD "Reducing Queue depth for untagged command.\n",
- p->host_no, CTL_OF_SCB(scb));
-#endif
p->dev_temp_queue_depth[tindex] = 1;
}
if ( (p->dev_active_cmds[tindex] >=
p->dev_temp_queue_depth[tindex]) ||
- time_after_eq(p->dev_last_reset[tindex], jiffies - 4 * HZ) )
+ (p->dev_flags[tindex] & (DEVICE_RESET_DELAY|DEVICE_WAS_BUSY)) ||
+ (p->flags & AHC_RESET_DELAY) )
{
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- printk(INFO_LEAD "Moving SCB to Delayed Queue.\n",
- p->host_no, CTL_OF_SCB(scb));
-#endif
scbq_insert_tail(&p->delayed_scbs[tindex], scb);
- if ( !timer_pending(&p->dev_timer[tindex]) &&
- !(p->dev_active_cmds[tindex]) )
- {
- p->dev_timer[tindex].expires = p->dev_last_reset[tindex] + (4 * HZ);
- add_timer(&p->dev_timer[tindex]);
- }
}
else
{
scb->flags &= ~SCB_WAITINGQ;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- printk(INFO_LEAD "Sending command %d/0x%x to QINFIFO\n", p->host_no,
- CTL_OF_SCB(scb), scb->hscb->tag, scb->flags);
-#endif
p->dev_active_cmds[tindex]++;
p->activescbs++;
if ( !(scb->tag_action) )
@@ -4037,16 +4023,6 @@ aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
}
if (sent)
{
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- {
- printk(INFO_LEAD "Sending commands to QINFIFO\n", p->host_no,
- -1, -1, -1);
- if ( (p->isr_count < 16) && (aic7xxx_panic_on_abort) &&
- (p->flags & AHC_PAGESCBS) )
- aic7xxx_check_scbs(p, "While sending commands to QINFIFO");
- }
-#endif
if (p->features & AHC_QUEUE_REGS)
aic_outb(p, p->qinfifonext, HNSCB_QOFF);
else
@@ -4147,12 +4123,21 @@ aic7xxx_timer(struct aic7xxx_host *p)
#else
spin_lock_irqsave(&io_request_lock, cpu_flags);
#endif
+ p->dev_timer_active &= ~(0x01 << MAX_TARGETS);
+ if ( (p->dev_timer_active & (0x01 << p->scsi_id)) &&
+ time_after_eq(jiffies, p->dev_expires[p->scsi_id]) )
+ {
+ p->flags &= ~AHC_RESET_DELAY;
+ p->dev_timer_active &= ~(0x01 << p->scsi_id);
+ }
for(i=0; i<MAX_TARGETS; i++)
{
- if ( timer_pending(&p->dev_timer[i]) &&
- time_before_eq(p->dev_timer[i].expires, jiffies) )
+ if ( (i != p->scsi_id) &&
+ (p->dev_timer_active & (0x01 << i)) &&
+ time_after_eq(jiffies, p->dev_expires[i]) )
{
- del_timer(&p->dev_timer[i]);
+ p->dev_timer_active &= ~(0x01 << i);
+ p->dev_flags[i] &= ~(DEVICE_RESET_DELAY|DEVICE_WAS_BUSY);
p->dev_temp_queue_depth[i] = p->dev_max_queue_depth[i];
j = 0;
while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) &&
@@ -4172,7 +4157,27 @@ aic7xxx_timer(struct aic7xxx_host *p)
*/
}
}
+ else if ( p->dev_timer_active & (0x01 << i) )
+ {
+ if ( p->dev_timer_active & (0x01 << MAX_TARGETS) )
+ {
+ if ( time_after_eq(p->dev_timer.expires, p->dev_expires[i]) )
+ {
+ p->dev_timer.expires = p->dev_expires[i];
+ }
+ }
+ else
+ {
+ p->dev_timer.expires = p->dev_expires[i];
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ }
+ }
+ }
+ if ( p->dev_timer_active & (0x01 << MAX_TARGETS) )
+ {
+ add_timer(&p->dev_timer);
}
+
aic7xxx_run_waiting_queues(p);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)
DRIVER_UNLOCK
@@ -4447,8 +4452,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
(scb->tag_action) &&
!(scb->flags & SCB_MSGOUT_BITS) )
{
- if ((scb->tag_action == MSG_ORDERED_Q_TAG) &&
- (p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS))
+ if (scb->tag_action == MSG_ORDERED_Q_TAG)
{
/*
* OK...the device seems able to accept tagged commands, but
@@ -4469,8 +4473,7 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
aic_outb(p, MSG_IDENTIFYFLAG, MSG_OUT);
aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
}
- else if ( (scb->tag_action == MSG_SIMPLE_Q_TAG) &&
- !(p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS) )
+ else if (scb->tag_action == MSG_SIMPLE_Q_TAG)
{
unsigned char i, reset = 0;
struct aic7xxx_scb *scbp;
@@ -4885,17 +4888,29 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
p->activescbs--;
scb->flags |= SCB_WAITINGQ | SCB_WAS_BUSY;
- if ( !timer_pending(&p->dev_timer[tindex]) )
+ if ( !(p->dev_timer_active & (0x01 << tindex)) )
{
+ p->dev_timer_active |= (0x01 << tindex);
if ( p->dev_active_cmds[tindex] )
{
- p->dev_timer[tindex].expires = jiffies + (HZ * 2);
- add_timer(&p->dev_timer[tindex]);
+ p->dev_expires[tindex] = jiffies + HZ;
}
else
{
- p->dev_timer[tindex].expires = jiffies + (HZ / 2);
- add_timer(&p->dev_timer[tindex]);
+ p->dev_expires[tindex] = jiffies + (HZ / 10);
+ }
+ if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) )
+ {
+ p->dev_timer.expires = p->dev_expires[tindex];
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ add_timer(&p->dev_timer);
+ }
+ else if ( time_after_eq(p->dev_timer.expires,
+ p->dev_expires[tindex]) )
+ {
+ del_timer(&p->dev_timer);
+ p->dev_timer.expires = p->dev_expires[tindex];
+ add_timer(&p->dev_timer);
}
}
#ifdef AIC7XXX_VERBOSE_DEBUGGING
@@ -4937,6 +4952,10 @@ aic7xxx_handle_seqint(struct aic7xxx_host *p, unsigned char intstat)
p->dev_last_queue_full[tindex] = 0;
p->dev_last_queue_full_count[tindex] = 0;
}
+ else
+ {
+ p->dev_flags[tindex] |= DEVICE_WAS_BUSY;
+ }
}
break;
}
@@ -5255,50 +5274,61 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
maxsync = AHC_SYNCRATE_FAST;
}
-
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
- if (aic7xxx_verbose > 0xffff)
- {
- printk(INFO_LEAD "Finished receipt of SDTR, parsing %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
- printk(INFO_LEAD "After find_syncrate() %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- aic7xxx_validate_offset(p, syncrate, &offset,
- target_scsirate & WIDEXFER);
- printk(INFO_LEAD "After validate_offset() %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
- printk(INFO_LEAD "Final values of Period/Offset as set: %d/%d\n",
- p->host_no, CTL_OF_SCB(scb), period, offset);
- }
- else
+ /*
+ * We might have a device that is starting negotiation with us
+ * before we can start up negotiation with it....be prepared to
+ * have a device ask for a higher speed then we want to give it
+ * in that case
+ */
+ if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) )
{
- syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
- aic7xxx_validate_offset(p, syncrate, &offset,
- target_scsirate & WIDEXFER);
- aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+ if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+ {
+ /*
+ * Not only is the device starting this up, but it also hasn't
+ * been scanned yet, so this would likely be our TUR or our
+ * INQUIRY command at scan time, so we need to use the
+ * settings from the SEEPROM if they existed. Of course, even
+ * if we didn't find a SEEPROM, we stuffed default values into
+ * the user settings anyway, so use those in all cases.
+ */
+ p->transinfo[tindex].goal_period =
+ p->transinfo[tindex].user_period;
+ p->transinfo[tindex].goal_offset =
+ p->transinfo[tindex].user_offset;
+ p->needsdtr_copy |= target_mask;
+ }
+ if ( !p->transinfo[tindex].goal_offset )
+ period = 255;
+ if ( p->transinfo[tindex].goal_period > period )
+ period = p->transinfo[tindex].goal_period;
}
-#else
+
syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
aic7xxx_validate_offset(p, syncrate, &offset,
target_scsirate & WIDEXFER);
aic7xxx_set_syncrate(p, syncrate, target, channel, period,
offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-#endif
- if (offset == 0)
+ /*
+ * Did we drop to async? If so, are we sending a reply? If we are,
+ * then we have to make sure that the reply value reflects the proper
+ * settings so we need to set the goal values according to what
+ * we need to send.
+ */
+ if ( (offset == 0) || (offset != saved_offset) ||
+ ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+ (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) )
{
- /*
- * Uhh ohh, things fell through to async....update the goal
- * items and the needsdtr_copy to reflect this...
- */
aic7xxx_set_syncrate(p, syncrate, target, channel, period,
- offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
- p->needsdtr_copy &= ~target_mask;
+ offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+ if ( offset == 0 )
+ {
+ p->needsdtr_copy &= ~target_mask;
+ }
}
+
/*
* Did we start this, if not, or if we went to low and had to
* go async, then send an SDTR back to the target
@@ -5313,32 +5343,6 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
}
else
{
- /*
- * Send a reply SDTR back. Even if we sent the first one, it
- * is valid to send another one out immediately to re-negotiate
- * things, and a few devices don't like getting rejects after
- * we already sent them one SDTR. Just send an SDTR for async
- * this time if need be (or for the correct params if we didn't
- * start all of this). If this is a Reject Reply type message,
- * then we've put the async settings into the goal area for
- * future reference (when we get the AWAITING_MSG interrupt).
- * If this is a case where we are responding to the target's
- * initiated SDTR, then leave our own goal and user values in
- * place (unless the device hasn't been scanned yet, in which
- * case, put the user values into the goal values so we don't
- * send out an Async message).
- */
- if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
- {
- p->transinfo[tindex].goal_width =
- p->transinfo[tindex].user_width;
- p->transinfo[tindex].goal_period =
- p->transinfo[tindex].user_period;
- p->transinfo[tindex].goal_offset =
- p->transinfo[tindex].user_offset;
- p->needwdtr_copy |= target_mask;
- p->needsdtr_copy |= target_mask;
- }
scb->flags &= ~SCB_MSGOUT_BITS;
scb->flags |= SCB_MSGOUT_SDTR;
aic_outb(p, HOST_MSG, MSG_OUT);
@@ -5407,12 +5411,12 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
* it contacted us first, mark it as such and copy the user stuff
* over to the goal stuff.
*/
- p->transinfo[tindex].goal_width =
- p->transinfo[tindex].user_width;
p->transinfo[tindex].goal_period =
p->transinfo[tindex].user_period;
p->transinfo[tindex].goal_offset =
p->transinfo[tindex].user_offset;
+ p->transinfo[tindex].goal_width =
+ p->transinfo[tindex].user_width;
p->needwdtr_copy |= target_mask;
p->needsdtr_copy |= target_mask;
}
@@ -5432,6 +5436,8 @@ aic7xxx_parse_msg(struct aic7xxx_host *p, struct aic7xxx_scb *scb)
{
p->needwdtr_copy &= ~target_mask;
bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+ aic7xxx_set_width(p, target, channel, lun, bus_width,
+ AHC_TRANS_GOAL|AHC_TRANS_QUITE);
break;
}
}
@@ -5808,23 +5814,19 @@ aic7xxx_handle_scsiint(struct aic7xxx_host *p, unsigned char intstat)
* Put this SCB back on the free list.
*/
aic7xxx_add_curscb_to_free_list(p);
- /*
- * XXX - If we queued an abort tag, go clean up the disconnected list.
- * We know that this particular SCB had to be the queued abort since
- * the disconnected SCB would have gotten a reconnect instead.
- * However, if this is an abort command, then DID_TIMEOUT isn't
- * appropriate, neither is returning the command for that matter.
- * What we need to do then is to let the command timeout again so
- * we get a reset since this abort just failed.
- */
#ifdef AIC7XXX_VERBOSE_DEBUGGING
if (aic7xxx_verbose > 0xffff)
printk(INFO_LEAD "Selection Timeout.\n", p->host_no, CTL_OF_SCB(scb));
#endif
- if (p->flags & SCB_QUEUED_ABORT)
+ if (scb->flags & SCB_QUEUED_ABORT)
{
+ /*
+ * We know that this particular SCB had to be the queued abort since
+ * the disconnected SCB would have gotten a reconnect instead.
+ * What we need to do then is to let the command timeout again so
+ * we get a reset since this abort just failed.
+ */
cmd->result = 0;
- scb->flags &= ~SCB_QUEUED_ABORT;
scb = NULL;
}
}
@@ -6241,12 +6243,6 @@ aic7xxx_isr(int irq, void *dev_id, struct pt_regs *regs)
aic7xxx_calculate_residual(p, scb);
}
cmd->result |= (aic7xxx_error(cmd) << 16);
- if (scb->tag_action)
- p->dev_flags[TARGET_INDEX(cmd)] |=
- DEVICE_TAGGED_SUCCESS | DEVICE_SUCCESS | DEVICE_PRESENT;
- else
- p->dev_flags[TARGET_INDEX(cmd)] |=
- DEVICE_SUCCESS | DEVICE_PRESENT;
aic7xxx_done(p, scb);
break;
}
@@ -6392,7 +6388,6 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
target_mask = (1 << tindex);
device->queue_depth = default_depth;
- p->dev_mid_level_queue_depth[tindex] = 3;
p->dev_temp_queue_depth[tindex] = 1;
p->dev_max_queue_depth[tindex] = 1;
p->tagenable &= ~target_mask;
@@ -6401,11 +6396,7 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
{
int tag_enabled = TRUE;
-#ifdef AIC7XXX_CMDS_PER_LUN
default_depth = AIC7XXX_CMDS_PER_LUN;
-#else
- default_depth = 8; /* Not many SCBs to work with. */
-#endif
if (!(p->discenable & target_mask))
{
@@ -6457,7 +6448,6 @@ aic7xxx_device_queue_depth(struct aic7xxx_host *p, Scsi_Device *device)
}
p->dev_max_queue_depth[tindex] = device->queue_depth;
p->dev_temp_queue_depth[tindex] = device->queue_depth;
- p->dev_mid_level_queue_depth[tindex] = device->queue_depth;
p->tagenable |= target_mask;
p->orderedtag |= target_mask;
device->tagged_queue = 1;
@@ -7452,7 +7442,6 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
}
p->host = host;
- p->last_reset = jiffies;
p->host_no = host->host_no;
host->unique_id = p->instance;
p->isr_count = 0;
@@ -7461,6 +7450,10 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
p->completeq.tail = NULL;
scbq_init(&p->scb_data->free_scbs);
scbq_init(&p->waiting_scbs);
+ init_timer(&p->dev_timer);
+ p->dev_timer.data = (unsigned long)p;
+ p->dev_timer.function = (void *)aic7xxx_timer;
+ p->dev_timer_active = 0;
for (i = 0; i < NUMBER(p->untagged_scbs); i++)
{
@@ -7479,16 +7472,12 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
p->dev_commands_sent[i] = 0;
p->dev_flags[i] = 0;
p->dev_active_cmds[i] = 0;
- p->dev_last_reset[i] = jiffies;
p->dev_last_queue_full[i] = 0;
p->dev_last_queue_full_count[i] = 0;
p->dev_max_queue_depth[i] = 1;
p->dev_temp_queue_depth[i] = 1;
- p->dev_mid_level_queue_depth[i] = 3;
+ p->dev_expires[i] = 0;
scbq_init(&p->delayed_scbs[i]);
- init_timer(&p->dev_timer[i]);
- p->dev_timer[i].data = (unsigned long)p;
- p->dev_timer[i].function = (void *)aic7xxx_timer;
}
printk(KERN_INFO "(scsi%d) <%s> found at ", p->host_no,
@@ -7538,10 +7527,9 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
}
aic_outb(p, 0, SEQ_FLAGS);
- /*
- * Detect SCB parameters and initialize the SCB array.
- */
detect_maxscb(p);
+
+
printk("%d/%d SCBs\n", p->scb_data->maxhscbs, p->scb_data->maxscbs);
if (aic7xxx_verbose & VERBOSE_PROBE2)
{
@@ -7660,7 +7648,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
aic_outb(p, p->scsi_id_b, SCSIID);
scsi_conf = aic_inb(p, SCSICONF + 1);
aic_outb(p, DFON | SPIOEN, SXFRCTL0);
- aic_outb(p, (scsi_conf & ENSPCHK) | term |
+ aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term |
ENSTIMER | ACTNEGEN, SXFRCTL1);
aic_outb(p, 0, SIMODE0);
aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -7677,7 +7665,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
aic_outb(p, p->scsi_id, SCSIID);
scsi_conf = aic_inb(p, SCSICONF);
aic_outb(p, DFON | SPIOEN, SXFRCTL0);
- aic_outb(p, (scsi_conf & ENSPCHK) | term |
+ aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term |
ENSTIMER | ACTNEGEN, SXFRCTL1);
aic_outb(p, 0, SIMODE0);
aic_outb(p, ENSELTIMO | ENSCSIRST | ENSCSIPERR, SIMODE1);
@@ -8156,6 +8144,21 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
scarray, p->sc_size, C46);
}
+ if (!have_seeprom)
+ {
+ p->sc_size = 128;
+ have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+ scarray, p->sc_size, p->sc_type);
+ if (!have_seeprom)
+ {
+ if(p->sc_type == C46)
+ have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+ scarray, p->sc_size, C56_66);
+ else
+ have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+ scarray, p->sc_size, C46);
+ }
+ }
break;
}
@@ -8187,7 +8190,8 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
sc->adapter_control &= ~CFAUTOTERM;
sc->adapter_control |= CFSTERM | CFWSTERM | CFLVDSTERM;
}
- p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
+ if (aic7xxx_extended)
+ p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
}
else
{
@@ -8341,7 +8345,8 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
}
else if (sc->device_flags[i] & CFNEWULTRAFORMAT)
{
- if ( (sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03 )
+ if ( ((sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03) &&
+ !(p->features & AHC_ULTRA2) )
{
sc->device_flags[i] &= ~CFXFER;
sc->device_flags[i] |= CFSYNCHISULTRA;
@@ -8622,12 +8627,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
current_p = current_p->next;
current_p->next = temp_p;
}
- if (aic7xxx_extended)
- {
- temp_p->flags |= AHC_EXTEND_TRANS_A;
- if (temp_p->flags & AHC_MULTI_CHANNEL)
- temp_p->flags |= AHC_EXTEND_TRANS_B;
- }
switch (type)
{
@@ -8834,6 +8833,10 @@ aic7xxx_detect(Scsi_Host_Template *template)
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
AHC_AIC7890_FE, 20,
32, C46 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_78902, AHC_AIC7890,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7890_FE, 20,
+ 32, C46 },
{PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_2940U2, AHC_AIC7890,
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
AHC_AIC7890_FE, 21,
@@ -8846,13 +8849,18 @@ aic7xxx_detect(Scsi_Host_Template *template)
AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
AHC_AIC7896_FE, 23,
32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_3950U2D, AHC_AIC7896,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
+ AHC_AIC7896_FE, 24,
+ 32, C56_66 },
+ {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
+ AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+ AHC_AIC7860_FE, 25,
+ 32, C46 },
};
unsigned short command;
unsigned int devconfig, i, oldverbose;
-#ifdef MMAPIO
- unsigned long page_offset, base;
-#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
struct pci_dev *pdev = NULL;
#else
@@ -9003,21 +9011,68 @@ aic7xxx_detect(Scsi_Host_Template *template)
temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK;
temp_p->unpause = INTEN;
temp_p->pause = temp_p->unpause | PAUSE;
+ if ( ((temp_p->base == 0) &&
+ (temp_p->mbase == 0)) ||
+ (temp_p->irq == 0) )
+ {
+ printk("aic7xxx: <%s> at PCI %d/%d\n",
+ board_names[aic_pdevs[i].board_name_index],
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
+ printk("aic7xxx: Controller disabled by BIOS, ignoring.\n");
+ kfree(temp_p);
+ temp_p = NULL;
+ continue;
+ }
#ifdef MMAPIO
- base = temp_p->mbase & PAGE_MASK;
- page_offset = temp_p->mbase - base;
+ {
+ unsigned long page_offset, base;
+
+ base = temp_p->mbase & PAGE_MASK;
+ page_offset = temp_p->mbase - base;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0)
- temp_p->maddr = ioremap_nocache(base, page_offset + 256);
+ temp_p->maddr = ioremap_nocache(base, page_offset + 256);
#else
- temp_p->maddr = vremap(base, page_offset + 256);
+ temp_p->maddr = vremap(base, page_offset + 256);
#endif
- if(temp_p->maddr)
- {
- temp_p->maddr += page_offset;
+ if(temp_p->maddr)
+ {
+ temp_p->maddr += page_offset;
+ /*
+ * We need to check the I/O with the MMAPed address. Some machines
+ * simply fail to work with MMAPed I/O and certain controllers.
+ */
+ if(aic_inb(temp_p, HCNTRL) == 0xff)
+ {
+ /*
+ * OK.....we failed our test....go back to programmed I/O
+ */
+ printk(KERN_INFO "aic7xxx: <%s> at PCI %d/%d\n",
+ board_names[aic_pdevs[i].board_name_index],
+ PCI_SLOT(temp_p->pci_device_fn),
+ PCI_FUNC(temp_p->pci_device_fn));
+ printk(KERN_INFO "aic7xxx: MMAPed I/O failed, reverting to "
+ "Programmed I/O.\n");
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+ iounmap((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
+#else
+ vfree((void *) (((unsigned long) temp_p->maddr) & PAGE_MASK));
+#endif
+ temp_p->maddr = 0;
+ }
+ }
}
#endif
+ /*
+ * We HAVE to make sure the first pause_sequencer() and all other
+ * subsequent I/O that isn't PCI config space I/O takes place
+ * after the MMAPed I/O region is configured and tested. The
+ * problem is the PowerPC architecture that doesn't support
+ * programmed I/O at all, so we have to have the MMAP I/O set up
+ * for this pause to even work on those machines.
+ */
pause_sequencer(temp_p);
/*
@@ -9052,44 +9107,36 @@ aic7xxx_detect(Scsi_Host_Template *template)
}
/*
- * Doing a switch based upon i is really gross, but since Justin
- * changed around the chip ID stuff, we can't use that any more.
- * Since we don't scan the devices the same way as FreeBSD, we end
- * up doing this gross hack in order to avoid totally splitting
- * away from Justin's init code in ahc_pci.c
+ * We need to set the CHNL? assignments before loading the SEEPROM
+ * The 3940 and 3985 cards (original stuff, not any of the later
+ * stuff) are 7870 and 7880 class chips. The Ultra2 stuff falls
+ * under 7896 and 7897. The 7895 is in a class by itself :)
*/
- switch (i)
+ switch (temp_p->chip & AHC_CHIPID_MASK)
{
- case 7: /* 3940 */
- case 12: /* 3940-Ultra */
- switch(PCI_SLOT(temp_p->pci_device_fn))
- {
- case 5:
- temp_p->flags |= AHC_CHNLB;
- break;
- default:
- break;
- }
- break;
-
- case 8: /* 3985 */
- case 13: /* 3985-Ultra */
- switch(PCI_SLOT(temp_p->pci_device_fn))
+ case AHC_AIC7870: /* 3840 / 3985 */
+ case AHC_AIC7880: /* 3840 UW / 3985 UW */
+ if(temp_p->flags & AHC_MULTI_CHANNEL)
{
- case 8:
- temp_p->flags |= AHC_CHNLB;
- break;
- case 12:
- temp_p->flags |= AHC_CHNLC;
- break;
- default:
- break;
+ switch(PCI_SLOT(temp_p->pci_device_fn))
+ {
+ case 5:
+ temp_p->flags |= AHC_CHNLB;
+ break;
+ case 8:
+ temp_p->flags |= AHC_CHNLB;
+ break;
+ case 12:
+ temp_p->flags |= AHC_CHNLC;
+ break;
+ default:
+ break;
+ }
}
break;
- case 15:
- case 18:
- case 19:
+ case AHC_AIC7895: /* 7895 */
+ case AHC_AIC7896: /* 7896/7 */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
if (PCI_FUNC(temp_p->pdev->devfn) != 0)
{
@@ -9257,13 +9304,10 @@ aic7xxx_detect(Scsi_Host_Template *template)
}
/*
- * We do another switch based on i so that we can exclude all
- * 3895 devices from the next option since the 3895 cards use
- * shared external SCB RAM while all other cards have dedicated
- * external SCB RAM per channel. Also exclude the 7850 and
- * 7860 based stuff since they can have garbage in the bit
- * that indicates external RAM and get some of this stuff
- * wrong as a result.
+ * We only support external SCB RAM on the 7895/6/7 chipsets.
+ * We could support it on the 7890/1 easy enough, but I don't
+ * know of any 7890/1 based cards that have it. I do know
+ * of 7895/6/7 cards that have it and they work properly.
*/
switch(temp_p->chip & AHC_CHIPID_MASK)
{
@@ -9327,9 +9371,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
aic_outb(temp_p, DFTHRSH_100, DSPCISTATUS);
}
- if (aic7xxx_extended)
- temp_p->flags |= AHC_EXTEND_TRANS_A;
-
if ( list_p == NULL )
{
list_p = current_p = temp_p;
@@ -10096,8 +10137,6 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
"message buffer\n", p->host_no, CTL_OF_SCB(scb));
scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
aic7xxx_error(scb->cmd) = DID_RESET;
- p->dev_flags[TARGET_INDEX(scb->cmd)] &=
- ~DEVICE_SUCCESS;
p->dev_flags[TARGET_INDEX(scb->cmd)] |=
BUS_DEVICE_RESET_PENDING;
/* Send the abort message to the active SCB. */
@@ -10118,8 +10157,6 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
"in use\n", p->host_no, CTL_OF_SCB(scb));
scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
aic7xxx_error(scb->cmd) = DID_RESET;
- p->dev_flags[TARGET_INDEX(scb->cmd)] &=
- ~DEVICE_SUCCESS;
p->dev_flags[TARGET_INDEX(scb->cmd)] |=
BUS_DEVICE_RESET_PENDING;
return(SCSI_RESET_ERROR);
@@ -10147,7 +10184,6 @@ aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
*/
scb->hscb->control |= MK_MESSAGE;
scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
- p->dev_flags[TARGET_INDEX(scb->cmd)] &= ~DEVICE_SUCCESS;
p->dev_flags[TARGET_INDEX(scb->cmd)] |=
BUS_DEVICE_RESET_PENDING;
if (hscb_index != SCB_LIST_NULL)
@@ -10227,7 +10263,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
{
mask = (0x01 << i);
printk(INFO_LEAD "dev_flags=0x%x, WDTR:%c/%c/%c, SDTR:%c/%c/%c,"
- " q_depth=%d:%d:%d\n",
+ " q_depth=%d:%d\n",
p->host_no, 0, i, 0, p->dev_flags[i],
(p->wdtr_pending & mask) ? 'Y' : 'N',
(p->needwdtr & mask) ? 'Y' : 'N',
@@ -10236,7 +10272,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
(p->needsdtr & mask) ? 'Y' : 'N',
(p->needsdtr_copy & mask) ? 'Y' : 'N',
p->dev_active_cmds[i],
- p->dev_max_queue_depth[i], p->dev_mid_level_queue_depth[i]);
+ p->dev_max_queue_depth[i] );
printk(INFO_LEAD "targ_scsirate=0x%x", p->host_no, 0, i, 0,
aic_inb(p, TARG_SCSIRATE + i));
if (p->features & AHC_ULTRA2)
@@ -10877,7 +10913,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
{
action = HOST_RESET;
}
- if ( ((jiffies - p->dev_last_reset[tindex]) < (HZ * 3)) &&
+ if ( (p->dev_flags[tindex] & DEVICE_RESET_DELAY) &&
!(action & (HOST_RESET | BUS_RESET)))
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
@@ -10889,23 +10925,14 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
}
action = BUS_RESET;
}
- if ( ((jiffies - p->last_reset) < (HZ * 3)) &&
- (action & (HOST_RESET | BUS_RESET)) )
+ if ( (p->flags & AHC_RESET_DELAY) &&
+ (action & (HOST_RESET | BUS_RESET)) )
{
if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
printk(INFO_LEAD "Reset called too soon after "
"last bus reset, delaying.\n", p->host_no, CTL_OF_CMD(cmd));
action = RESET_DELAY;
}
- if ( (action & (BUS_RESET | HOST_RESET)) && (p->flags & AHC_IN_RESET)
- && ((jiffies - p->reset_start) > (2 * HZ * 3)) )
- {
- printk(KERN_ERR "(scsi%d:%d:%d:%d) Yikes!! Card must have left to go "
- "back to Adaptec!!\n", p->host_no, CTL_OF_CMD(cmd));
- unpause_sequencer(p, FALSE);
- DRIVER_UNLOCK
- return(SCSI_RESET_SNOOZE);
- }
/*
* By this point, we want to already know what we are going to do and
* only have the following code implement our course of action.
@@ -10937,15 +10964,23 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
case BUS_RESET:
case HOST_RESET:
default:
- p->reset_start = jiffies;
- p->flags |= AHC_IN_RESET;
+ p->flags |= AHC_IN_RESET | AHC_RESET_DELAY;
+ p->dev_expires[p->scsi_id] = jiffies + (3 * HZ);
+ p->dev_timer_active |= (0x01 << p->scsi_id);
+ if ( !(p->dev_timer_active & (0x01 << MAX_TARGETS)) ||
+ time_after_eq(p->dev_timer.expires, p->dev_expires[p->scsi_id]) )
+ {
+ del_timer(&p->dev_timer);
+ p->dev_timer.expires = p->dev_expires[p->scsi_id];
+ add_timer(&p->dev_timer);
+ p->dev_timer_active |= (0x01 << MAX_TARGETS);
+ }
aic7xxx_reset_channel(p, cmd->channel, TRUE);
if ( (p->features & AHC_TWIN) && (action & HOST_RESET) )
{
aic7xxx_reset_channel(p, cmd->channel ^ 0x01, TRUE);
restart_sequencer(p);
}
- p->last_reset = jiffies;
if (action != HOST_RESET)
result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
else
@@ -10960,9 +10995,27 @@ aic7xxx_reset(Scsi_Cmnd *cmd, unsigned int flags)
p->msg_len = 0;
}
aic7xxx_run_done_queue(p, TRUE);
+ /*
+ * If this a SCSI_RESET_SYNCHRONOUS then the command we were given is
+ * in need of being re-started, so send it on through to aic7xxx_queue
+ * and let it set until the delay is over. This keeps it from dying
+ * entirely and avoids getting a bogus dead command back through the
+ * mid-level code due to too many retries.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,132)
+ if ( flags & SCSI_RESET_SYNCHRONOUS )
+ {
+ cmd->result = DID_BUS_BUSY << 16;
+ cmd->done(cmd);
+ }
+#endif
p->flags &= ~AHC_IN_RESET;
- /* We can't rely on run_waiting_queues to unpause the sequencer for
- * PCI based controllers since we use AAP */
+ /*
+ * We can't rely on run_waiting_queues to unpause the sequencer for
+ * PCI based controllers since we use AAP. NOTE: this also sets
+ * the timer for the one command we might have queued in the case
+ * of a synch reset.
+ */
aic7xxx_run_waiting_queues(p);
unpause_sequencer(p, FALSE);
DRIVER_UNLOCK
diff --git a/drivers/scsi/aic7xxx/aic7xxx.reg b/drivers/scsi/aic7xxx/aic7xxx.reg
index 7356d3488..58b2100f5 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.reg
+++ b/drivers/scsi/aic7xxx/aic7xxx.reg
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.reg,v 1.5 1998/10/19 21:28:34 ralf Exp $
+ * $Id: aic7xxx.reg,v 1.6 1999/02/01 22:31:10 ralf Exp $
*/
/*
@@ -461,7 +461,7 @@ register SEQCTL {
* Sequencer RAM Data (p. 3-34)
* Single byte window into the Scratch Ram area starting at the address
* specified by SEQADDR0 and SEQADDR1. To write a full word, simply write
- * four bytes in sucessesion. The SEQADDRs will increment after the most
+ * four bytes in succession. The SEQADDRs will increment after the most
* significant byte is written
*/
register SEQRAM {
diff --git a/drivers/scsi/aic7xxx_proc.c b/drivers/scsi/aic7xxx_proc.c
index d3d1b1ea3..6e5eca864 100644
--- a/drivers/scsi/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx_proc.c
@@ -31,7 +31,7 @@
#define BLS (&aic7xxx_buffer[size])
#define HDRB \
-" < 512 512-1K 1-2K 2-4K 4-8K 8-16K 16-32K 32-64K 64-128K >128K"
+" < 2K 2K+ 4K+ 8K+ 16K+ 32K+ 64K+ 128K+"
#ifdef PROC_DEBUG
extern int vsprintf(char *, const char *, va_list);
@@ -86,7 +86,7 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
int size = 0;
unsigned char i;
struct aic7xxx_xferstats *sp;
- unsigned char target, lun;
+ unsigned char target;
HBAptr = NULL;
@@ -130,15 +130,12 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
size = 4096;
for (target = 0; target < MAX_TARGETS; target++)
{
- for (lun = 0; lun < MAX_LUNS; lun++)
- {
- if (p->stats[target][lun].xfers != 0)
+ if (p->dev_flags[target] & DEVICE_PRESENT)
#ifdef AIC7XXX_PROC_STATS
- size += 512;
+ size += 512;
#else
- size += 256;
+ size += 256;
#endif
- }
}
if (aic7xxx_buffer_size != size)
{
@@ -272,85 +269,83 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
size += sprintf(BLS, "%d}\n", p->dev_max_queue_depth[i]);
size += sprintf(BLS, "\n");
- size += sprintf(BLS, "Statistics:\n");
+ size += sprintf(BLS, "Statistics:\n\n");
for (target = 0; target < MAX_TARGETS; target++)
{
- for (lun = 0; lun < MAX_LUNS; lun++)
+ sp = &p->stats[target];
+ if ((p->dev_flags[target] & DEVICE_PRESENT) == 0)
{
- sp = &p->stats[target][lun];
- if (sp->xfers == 0)
- {
- continue;
- }
- if (p->features & AHC_TWIN)
+ continue;
+ }
+ if (p->features & AHC_TWIN)
+ {
+ size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+ p->host_no, (target >> 3), (target & 0x7), 0);
+ }
+ else
+ {
+ size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
+ p->host_no, 0, target, 0);
+ }
+ size += sprintf(BLS, " Device using %s/%s",
+ (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ?
+ "Wide" : "Narrow",
+ (p->transinfo[target].cur_offset != 0) ?
+ "Sync transfers at " : "Async transfers.\n" );
+ if (p->transinfo[target].cur_offset != 0)
+ {
+ struct aic7xxx_syncrate *sync_rate;
+ int period = p->transinfo[target].cur_period;
+ int rate = (p->transinfo[target].cur_width ==
+ MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
+
+ sync_rate = aic7xxx_find_syncrate(p, &period, AHC_SYNCRATE_ULTRA2);
+ if (sync_rate != NULL)
{
- size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
- p->host_no, (target >> 3), (target & 0x7), lun);
+ size += sprintf(BLS, "%s MByte/sec, offset %d\n",
+ sync_rate->rate[rate],
+ p->transinfo[target].cur_offset );
}
else
{
- size += sprintf(BLS, "(scsi%d:%d:%d:%d)\n",
- p->host_no, 0, target, lun);
- }
- size += sprintf(BLS, " Device using %s/%s\n",
- (p->transinfo[target].cur_width == MSG_EXT_WDTR_BUS_16_BIT) ?
- "Wide" : "Narrow",
- (p->transinfo[target].cur_offset != 0) ?
- "Sync transfers at" : "Async transfers." );
- if (p->transinfo[target].cur_offset != 0)
- {
- struct aic7xxx_syncrate *sync_rate;
- int period = p->transinfo[target].cur_period;
- int rate = (p->transinfo[target].cur_width ==
- MSG_EXT_WDTR_BUS_16_BIT) ? 1 : 0;
-
- sync_rate = aic7xxx_find_syncrate(p, &period, AHC_SYNCRATE_ULTRA2);
- if (sync_rate != NULL)
- {
- size += sprintf(BLS, " %s MByte/sec, offset %d\n",
- sync_rate->rate[rate],
- p->transinfo[target].cur_offset );
- }
- else
- {
- size += sprintf(BLS, " 3.3 MByte/sec, offset %d\n",
- p->transinfo[target].cur_offset );
- }
+ size += sprintf(BLS, "3.3 MByte/sec, offset %d\n",
+ p->transinfo[target].cur_offset );
}
- size += sprintf(BLS, " Device Negotiation Settings\n");
- size += sprintf(BLS, " Period Offset Bus Width\n");
- size += sprintf(BLS, "User %03d %03d %d\n",
- p->transinfo[target].user_period,
- p->transinfo[target].user_offset,
- p->transinfo[target].user_width);
- size += sprintf(BLS, "Goal %03d %03d %d\n",
- p->transinfo[target].goal_period,
- p->transinfo[target].goal_offset,
- p->transinfo[target].goal_width);
- size += sprintf(BLS, "Current %03d %03d %d\n",
- p->transinfo[target].cur_period,
- p->transinfo[target].cur_offset,
- p->transinfo[target].cur_width);
- size += sprintf(BLS, " Total transfers %ld (%ld read;%ld written)\n",
- sp->xfers, sp->r_total, sp->w_total);
- size += sprintf(BLS, " blks(512) rd=%ld; blks(512) wr=%ld\n",
- sp->r_total512, sp->w_total512);
+ }
+ size += sprintf(BLS, " Transinfo settings: ");
+ size += sprintf(BLS, "current(%d/%d/%d), ",
+ p->transinfo[target].cur_period,
+ p->transinfo[target].cur_offset,
+ p->transinfo[target].cur_width);
+ size += sprintf(BLS, "goal(%d/%d/%d), ",
+ p->transinfo[target].goal_period,
+ p->transinfo[target].goal_offset,
+ p->transinfo[target].goal_width);
+ size += sprintf(BLS, "user(%d/%d/%d)\n",
+ p->transinfo[target].user_period,
+ p->transinfo[target].user_offset,
+ p->transinfo[target].user_width);
#ifdef AIC7XXX_PROC_STATS
- size += sprintf(BLS, "%s\n", HDRB);
- size += sprintf(BLS, " Reads:");
- for (i = 0; i < NUMBER(sp->r_bins); i++)
- {
- size += sprintf(BLS, "%6ld ", sp->r_bins[i]);
- }
- size += sprintf(BLS, "\n");
- size += sprintf(BLS, "Writes:");
- for (i = 0; i < NUMBER(sp->w_bins); i++)
- {
- size += sprintf(BLS, "%6ld ", sp->w_bins[i]);
- }
-#endif /* AIC7XXX_PROC_STATS */
- size += sprintf(BLS, "\n\n");
+ size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n",
+ sp->r_total + sp->w_total, sp->r_total, sp->w_total);
+ size += sprintf(BLS, "%s\n", HDRB);
+ size += sprintf(BLS, " Reads:");
+ for (i = 0; i < NUMBER(sp->r_bins); i++)
+ {
+ size += sprintf(BLS, " %7ld", sp->r_bins[i]);
+ }
+ size += sprintf(BLS, "\n");
+ size += sprintf(BLS, " Writes:");
+ for (i = 0; i < NUMBER(sp->w_bins); i++)
+ {
+ size += sprintf(BLS, " %7ld", sp->w_bins[i]);
}
+ size += sprintf(BLS, "\n");
+#else
+ size += sprintf(BLS, " Total transfers %ld (%ld reads and %ld writes)\n",
+ sp->r_total + sp->w_total, sp->r_total, sp->w_total);
+#endif /* AIC7XXX_PROC_STATS */
+ size += sprintf(BLS, "\n\n");
}
if (size >= aic7xxx_buffer_size)
diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c
index 60d461182..e48f6ad81 100644
--- a/drivers/scsi/atari_dma_emul.c
+++ b/drivers/scsi/atari_dma_emul.c
@@ -429,7 +429,7 @@ scsi_bus_error:
if (eff_addr == &hades_psdm_reg)
{
/*
- * Bus error occured while reading the pseudo
+ * Bus error occurred while reading the pseudo
* DMA register. Time out.
*/
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
new file mode 100644
index 000000000..96280a8c3
--- /dev/null
+++ b/drivers/scsi/atp870u.c
@@ -0,0 +1,2037 @@
+/* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $
+ * linux/kernel/atp870u.c
+ *
+ * Copyright (C) 1997 Wu Ching Chen
+ * 2.1.x update (C) 1998 Krzysztof G. Baranowski
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+#include <linux/blk.h>
+#include "scsi.h"
+#include "hosts.h"
+
+
+#include "atp870u.h"
+
+#include<linux/stat.h>
+
+struct proc_dir_entry proc_scsi_atp870u = {
+ PROC_SCSI_ATP870U, 7, "atp870u",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+void mydlyu(unsigned int);
+/*
+static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $";
+*/
+
+static unsigned char admaxu=1,host_idu[2],chip_veru[2],scam_on[2],global_map[2];
+static unsigned short int active_idu[2],wide_idu[2],sync_idu,ultra_map[2];
+static int workingu[2]={0,0};
+static Scsi_Cmnd *querequ[2][qcnt],*curr_req[2][16];
+static unsigned char devspu[2][16] = {{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
+ {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}};
+static unsigned char dirctu[2][16],last_cmd[2],in_snd[2],in_int[2];
+static unsigned char ata_cdbu[2][16];
+static unsigned int ioportu[2]={0,0};
+static unsigned int irqnumu[2]={0,0};
+static unsigned short int pciportu[2];
+static unsigned long prdaddru[2][16],tran_lenu[2][16],last_lenu[2][16];
+static unsigned char prd_tableu[2][16][1024];
+static unsigned char *prd_posu[2][16];
+static unsigned char quhdu[2],quendu[2];
+static unsigned char devtypeu[2][16] = {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+static struct Scsi_Host * atp_host[2]={NULL,NULL};
+
+static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned short int tmpcip,id;
+ unsigned char i,j,h,tarid,lun;
+ unsigned char *prd;
+ Scsi_Cmnd *workrequ;
+ unsigned int workportu,tmport;
+ unsigned long adrcntu,k;
+ int errstus;
+
+ for ( h=0; h < 2; h++ )
+ {
+ if ( ( irq & 0x0f ) == irqnumu[h] )
+ {
+ goto irq_numok;
+ }
+ }
+ return;
+irq_numok:
+ in_int[h]=1;
+ workportu=ioportu[h];
+ tmport=workportu;
+
+ if ( workingu[h] != 0 )
+ {
+ tmport += 0x1f;
+ j=inb(tmport);
+ tmpcip=pciportu[h];
+ if ((inb(tmpcip) & 0x08) != 0)
+ {
+ tmpcip += 0x2;
+ while((inb(tmpcip) & 0x08) != 0);
+ }
+ tmpcip=pciportu[h];
+ outb(0x00,tmpcip);
+ tmport -=0x08;
+ i=inb(tmport);
+ if ((j & 0x40) == 0)
+ {
+ if ((last_cmd[h] & 0x40) == 0)
+ {
+ last_cmd[h]=0xff;
+ }
+ }
+ else
+ {
+ last_cmd[h] |= 0x40;
+ }
+ tmport -= 0x02;
+ tarid=inb(tmport);
+ tmport += 0x02;
+ if ((tarid & 0x40) != 0)
+ {
+ tarid=(tarid & 0x07) | 0x08;
+ }
+ else
+ {
+ tarid &= 0x07;
+ }
+ if ( i == 0x85 )
+ {
+ if (wide_idu[h] != 0)
+ {
+ tmport=workportu+0x1b;
+ j=inb(tmport) & 0x0e;
+ j |= 0x01;
+ outb(j,tmport);
+ }
+ if (((quhdu[h] != quendu[h]) || (last_cmd[h] != 0xff)) &&
+ (in_snd[h] == 0))
+ {
+ send_s870(h);
+ }
+ in_int[h]=0;
+ return;
+ }
+ if ( i == 0x21 )
+ {
+ tmport -= 0x05;
+ adrcntu=0;
+ ((unsigned char *)&adrcntu)[2]=inb(tmport++);
+ ((unsigned char *)&adrcntu)[1]=inb(tmport++);
+ ((unsigned char *)&adrcntu)[0]=inb(tmport);
+ k=last_lenu[h][tarid];
+ k -= adrcntu;
+ tran_lenu[h][tarid]= k;
+ last_lenu[h][tarid]=adrcntu;
+ tmport -= 0x04;
+ outb(0x41,tmport);
+ tmport += 0x08;
+ outb(0x08,tmport);
+ in_int[h]=0;
+ return ;
+ }
+
+ if ((i == 0x80) || (i == 0x8f))
+ {
+ lun=0;
+ tmport -= 0x07;
+ j=inb(tmport);
+ if ( j == 0x44 )
+ {
+ tmport += 0x0d;
+ lun=inb(tmport) & 0x07;
+ }
+ else
+ {
+ if ( j == 0x41 )
+ {
+ tmport += 0x02;
+ adrcntu=0;
+ ((unsigned char *)&adrcntu)[2]=inb(tmport++);
+ ((unsigned char *)&adrcntu)[1]=inb(tmport++);
+ ((unsigned char *)&adrcntu)[0]=inb(tmport);
+ k=last_lenu[h][tarid];
+ k -= adrcntu;
+ tran_lenu[h][tarid]= k;
+ last_lenu[h][tarid]=adrcntu;
+ tmport += 0x04;
+ outb(0x08,tmport);
+ in_int[h]=0;
+ return ;
+ }
+ else
+ {
+ outb(0x46,tmport);
+ dirctu[h][tarid]=0x00;
+ tmport += 0x02;
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ tmport+=0x03;
+ outb(0x08,tmport);
+ in_int[h]=0;
+ return;
+ }
+ }
+ tmport=workportu + 0x10;
+ outb(0x45,tmport);
+ tmport += 0x06;
+ tarid=inb(tmport);
+ if ((tarid & 0x10) != 0)
+ {
+ tarid=(tarid & 0x07) | 0x08;
+ }
+ else
+ {
+ tarid &= 0x07;
+ }
+ workrequ=curr_req[h][tarid];
+ tmport=workportu + 0x0f;
+ outb(lun,tmport);
+ tmport += 0x02;
+ outb(devspu[h][tarid],tmport++);
+ adrcntu=tran_lenu[h][tarid];
+ k=last_lenu[h][tarid];
+ outb(((unsigned char *)&k)[2],tmport++);
+ outb(((unsigned char *)&k)[1],tmport++);
+ outb(((unsigned char *)&k)[0],tmport++);
+ j=tarid;
+ if ( tarid > 7 )
+ {
+ j = (j & 0x07) | 0x40;
+ }
+ j |= dirctu[h][tarid];
+ outb(j,tmport++);
+ outb(0x80,tmport);
+ tmport=workportu + 0x1b;
+ j=inb(tmport) & 0x0e;
+ id=1;
+ id=id << tarid;
+ if ((id & wide_idu[h]) != 0)
+ {
+ j |= 0x01;
+ }
+ outb(j,tmport);
+ if ( last_lenu[h][tarid] == 0 )
+ {
+ tmport=workportu + 0x18;
+ outb(0x08,tmport);
+ in_int[h]=0;
+ return ;
+ }
+ prd=prd_posu[h][tarid];
+ while ( adrcntu != 0 )
+ {
+ id=((unsigned short int *)(prd))[2];
+ if ( id == 0 )
+ {
+ k=0x10000;
+ }
+ else
+ {
+ k=id;
+ }
+ if ( k > adrcntu )
+ {
+ ((unsigned short int *)(prd))[2] =(unsigned short int)
+ (k - adrcntu);
+ ((unsigned long *)(prd))[0] += adrcntu;
+ adrcntu=0;
+ prd_posu[h][tarid]=prd;
+ }
+ else
+ {
+ adrcntu -= k;
+ prdaddru[h][tarid] += 0x08;
+ prd += 0x08;
+ if ( adrcntu == 0 )
+ {
+ prd_posu[h][tarid]=prd;
+ }
+ }
+ }
+ tmpcip=pciportu[h] + 0x04;
+ outl(prdaddru[h][tarid],tmpcip);
+ tmpcip -= 0x02;
+ outb(0x06,tmpcip);
+ outb(0x00,tmpcip);
+ tmpcip -= 0x02;
+ tmport=workportu + 0x18;
+ if ( dirctu[h][tarid] != 0 )
+ {
+ outb(0x08,tmport);
+ outb(0x01,tmpcip);
+ in_int[h]=0;
+ return;
+ }
+ outb(0x08,tmport);
+ outb(0x09,tmpcip);
+ in_int[h]=0;
+ return;
+ }
+
+ workrequ=curr_req[h][tarid];
+ if ( i == 0x42 )
+ {
+ errstus=0x02;
+ workrequ->result=errstus;
+ goto go_42;
+ }
+ if ( i == 0x16 )
+ {
+ errstus=0;
+ tmport -= 0x08;
+ errstus=inb(tmport);
+ workrequ->result=errstus;
+/* if ( errstus == 0x02 )
+ {
+ tmport +=0x10;
+ if ((inb(tmport) & 0x80) != 0)
+ {
+ printk(" autosense ");
+ }
+ tmport -=0x09;
+ outb(0,tmport);
+ tmport=workportu+0x3a;
+ outb((unsigned char)(inb(tmport) | 0x10),tmport);
+ tmport -= 0x39;
+
+ outb(0x08,tmport++);
+ outb(0x7f,tmport++);
+ outb(0x03,tmport++);
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ outb(0x0e,tmport++);
+ outb(0x00,tmport);
+ tmport+=0x07;
+ outb(0x00,tmport++);
+ tmport++;
+ outb(devspu[h][workrequ->target],tmport++);
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ outb(0x0e,tmport++);
+ tmport+=0x03;
+ outb(0x09,tmport);
+ tmport+=0x07;
+ i=0;
+ adrcntu=(unsigned long)(&workrequ->sense_buffer[0]);
+get_sens:
+ j=inb(tmport);
+ if ((j & 0x01) != 0)
+ {
+ tmport-=0x06;
+ (unsigned char)(((caddr_t) adrcntu)[i++])=inb(tmport);
+ tmport+=0x06;
+ goto get_sens;
+ }
+ if ((j & 0x80) == 0)
+ {
+ goto get_sens;
+ }
+ if ((j & 0x40) == 0)
+ {
+ tmport-=0x08;
+ i=inb(tmport);
+ }
+ tmport=workportu+0x3a;
+ outb((unsigned char)(inb(tmport) & 0xef),tmport);
+ tmport=workportu+0x01;
+ outb(0x2c,tmport);
+ tmport += 0x15;
+ outb(0x80,tmport);
+ } */
+go_42:
+ (*workrequ->scsi_done)(workrequ);
+ curr_req[h][tarid]=0;
+ workingu[h]--;
+ if (wide_idu[h] != 0)
+ {
+ tmport=workportu+0x1b;
+ j=inb(tmport) & 0x0e;
+ j |= 0x01;
+ outb(j,tmport);
+ }
+ if (((last_cmd[h] != 0xff) || (quhdu[h] != quendu[h])) &&
+ (in_snd[h] == 0))
+ {
+ send_s870(h);
+ }
+ in_int[h]=0;
+ return;
+ }
+ if ( i == 0x4f )
+ {
+ i=0x89;
+ }
+ i &= 0x0f;
+ if ( i == 0x09 )
+ {
+ tmpcip=tmpcip+4;
+ outl(prdaddru[h][tarid],tmpcip);
+ tmpcip=tmpcip-2;
+ outb(0x06,tmpcip);
+ outb(0x00,tmpcip);
+ tmpcip=tmpcip-2;
+ tmport=workportu+0x10;
+ outb(0x41,tmport);
+ dirctu[h][tarid]=0x00;
+ tmport += 0x08;
+ outb(0x08,tmport);
+ outb(0x09,tmpcip);
+ in_int[h]=0;
+ return;
+ }
+ if ( i == 0x08 )
+ {
+ tmpcip=tmpcip+4;
+ outl(prdaddru[h][tarid],tmpcip);
+ tmpcip=tmpcip-2;
+ outb(0x06,tmpcip);
+ outb(0x00,tmpcip);
+ tmpcip=tmpcip-2;
+ tmport=workportu+0x10;
+ outb(0x41,tmport);
+ tmport += 0x05;
+ outb((unsigned char)(inb(tmport) | 0x20),tmport);
+ dirctu[h][tarid]=0x20;
+ tmport += 0x03;
+ outb(0x08,tmport);
+ outb(0x01,tmpcip);
+ in_int[h]=0;
+ return;
+ }
+ tmport -= 0x07;
+ if ( i == 0x0a )
+ {
+ outb(0x30,tmport);
+ }
+ else
+ {
+ outb(0x46,tmport);
+ }
+ dirctu[h][tarid]=0x00;
+ tmport += 0x02;
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ outb(0x00,tmport++);
+ tmport+=0x03;
+ outb(0x08,tmport);
+ in_int[h]=0;
+ return;
+ }
+ else
+ {
+ tmport=workportu+0x17;
+ inb(tmport);
+ workingu[h]=0;
+ in_int[h]=0;
+ return;
+ }
+}
+
+int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done)(Scsi_Cmnd *))
+{
+ unsigned char i,h;
+ unsigned long flags;
+ unsigned short int m;
+ unsigned int tmport;
+
+ for( h=0; h <= admaxu; h++ )
+ {
+ if ( req_p->host == atp_host[h] )
+ {
+ goto host_ok;
+ }
+ }
+ return 0;
+host_ok:
+ if ( req_p->channel != 0 )
+ {
+ req_p->result = 0x00040000;
+ done(req_p);
+ return 0;
+ }
+ m=1;
+ m= m << req_p->target;
+ if ( ( m & active_idu[h] ) == 0 )
+ {
+ req_p->result = 0x00040000;
+ done(req_p);
+ return 0;
+ }
+ if (done)
+ {
+ req_p->scsi_done = done;
+ }
+ else
+ {
+ printk("atp870u_queuecommand: done can't be NULL\n");
+ req_p->result = 0;
+ done(req_p);
+ return 0;
+ }
+ quendu[h]++;
+ if ( quendu[h] >= qcnt )
+ {
+ quendu[h]=0;
+ }
+ wait_que_empty:
+ if ( quhdu[h] == quendu[h] )
+ {
+ goto wait_que_empty;
+ }
+ save_flags(flags);
+ cli();
+ querequ[h][quendu[h]]=req_p;
+ if ( quendu[h] == 0 )
+ {
+ i=qcnt-1;
+ }
+ else
+ {
+ i=quendu[h]-1;
+ }
+ tmport = ioportu[h]+0x1c;
+ restore_flags(flags);
+ if ((inb(tmport) == 0) && (in_int[h] == 0) && (in_snd[h] == 0))
+ {
+ send_s870(h);
+ }
+ return 0;
+}
+
+void mydlyu(unsigned int dlycnt )
+{
+ unsigned int i ;
+ for ( i = 0 ; i < dlycnt ; i++ )
+ {
+ inb(0x80);
+ }
+}
+
+void send_s870(unsigned char h)
+{
+ unsigned int tmport;
+ Scsi_Cmnd *workrequ;
+ unsigned long flags;
+ unsigned int i;
+ unsigned char j,tarid;
+ unsigned char *prd;
+ unsigned short int tmpcip,w;
+ unsigned long l,bttl;
+ unsigned int workportu;
+ struct scatterlist * sgpnt;
+
+ save_flags(flags);
+ cli();
+ if ( in_snd[h] != 0 )
+ {
+ restore_flags(flags);
+ return;
+ }
+ in_snd[h]=1;
+ if ((last_cmd[h] != 0xff) && ((last_cmd[h] & 0x40) != 0))
+ {
+ last_cmd[h] &= 0x0f;
+ workrequ=curr_req[h][last_cmd[h]];
+ goto cmd_subp;
+ }
+ workingu[h]++;
+ j=quhdu[h];
+ quhdu[h]++;
+ if ( quhdu[h] >= qcnt )
+ {
+ quhdu[h]=0;
+ }
+ workrequ=querequ[h][quhdu[h]];
+ if ( curr_req[h][workrequ->target] == 0 )
+ {
+ curr_req[h][workrequ->target]=workrequ;
+ last_cmd[h]=workrequ->target;
+ goto cmd_subp;
+ }
+ quhdu[h]=j;
+ workingu[h]--;
+ in_snd[h]=0;
+ restore_flags(flags);
+ return ;
+cmd_subp:
+ workportu=ioportu[h];
+ tmport=workportu+0x1f;
+ if ((inb(tmport) & 0xb0) != 0)
+ {
+ goto abortsnd;
+ }
+ tmport=workportu+0x1c;
+ if ( inb(tmport) == 0 )
+ {
+ goto oktosend;
+ }
+abortsnd:
+ last_cmd[h] |= 0x40;
+ in_snd[h]=0;
+ restore_flags(flags);
+ return;
+oktosend:
+ memcpy(&ata_cdbu[h][0], &workrequ->cmnd[0], workrequ->cmd_len);
+ if ( ata_cdbu[h][0] == 0x25 )
+ {
+ if ( workrequ->request_bufflen > 8 )
+ {
+ workrequ->request_bufflen=0x08;
+ }
+ }
+ if ( ata_cdbu[h][0] == 0x12 )
+ {
+ if ( workrequ->request_bufflen > 0x24 )
+ {
+ workrequ->request_bufflen = 0x24;
+ ata_cdbu[h][4]=0x24;
+ }
+ }
+
+ tmport=workportu+0x1b;
+ j=inb(tmport) & 0x0e;
+ tarid=workrequ->target;
+ w=1;
+ w = w << tarid;
+ if ((w & wide_idu[h]) != 0)
+ {
+ j |= 0x01;
+ }
+ outb(j,tmport);
+ tmport=workportu;
+ outb(workrequ->cmd_len,tmport++);
+ outb(0x2c,tmport++);
+ outb(0xcf,tmport++);
+ for ( i=0 ; i < workrequ->cmd_len ; i++ )
+ {
+ outb(ata_cdbu[h][i],tmport++);
+ }
+ tmport=workportu+0x0f;
+ outb(0x00,tmport);
+ tmport+=0x02;
+ outb(devspu[h][tarid],tmport++);
+ if (workrequ->use_sg)
+ {
+
+ l=0;
+ sgpnt = (struct scatterlist *) workrequ->request_buffer;
+ for(i=0; i<workrequ->use_sg; i++)
+ {
+ if(sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
+ {
+ panic("Foooooooood fight!");
+ }
+ l += sgpnt[i].length;
+ }
+ }
+ else
+ {
+ l=workrequ->request_bufflen;
+ }
+ outb((unsigned char)(((unsigned char *)(&l))[2]),tmport++);
+ outb((unsigned char)(((unsigned char *)(&l))[1]),tmport++);
+ outb((unsigned char)(((unsigned char *)(&l))[0]),tmport++);
+ j=tarid;
+ last_lenu[h][j]=l;
+ tran_lenu[h][j]=0;
+ if ((j & 0x08) != 0)
+ {
+ j=(j & 0x07) | 0x40;
+ }
+ if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) ||
+ (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15))
+ {
+ outb((unsigned char)(j | 0x20),tmport++);
+ }
+ else
+ {
+ outb(j,tmport++);
+ }
+ outb(0x80,tmport);
+ tmport=workportu + 0x1c;
+ dirctu[h][tarid]=0;
+ if ( l == 0 )
+ {
+ if ( inb(tmport) == 0 )
+ {
+ tmport=workportu+0x18;
+ outb(0x08,tmport);
+ }
+ else
+ {
+ last_cmd[h] |= 0x40;
+ }
+ in_snd[h]=0;
+ restore_flags(flags);
+ return;
+ }
+ tmpcip=pciportu[h];
+ prd=&prd_tableu[h][tarid][0];
+ prd_posu[h][tarid]=prd;
+ if (workrequ->use_sg)
+ {
+ sgpnt = (struct scatterlist *) workrequ->request_buffer;
+ i=0;
+ for(j=0; j<workrequ->use_sg; j++)
+ {
+ (unsigned long)(((unsigned long *)(prd))[i >> 1])=(unsigned long)sgpnt[j].address;
+ (unsigned short int)(((unsigned short int *)(prd))[i+2])=sgpnt[j].length;
+ (unsigned short int)(((unsigned short int *)(prd))[i+3])=0;
+ i +=0x04;
+ }
+ (unsigned short int)(((unsigned short int *)(prd))[i-1])=0x8000;
+ }
+ else
+ {
+ bttl=(unsigned long)workrequ->request_buffer;
+ l=workrequ->request_bufflen;
+ i=0;
+ while ( l > 0x10000 )
+ {
+ (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x0000;
+ (unsigned short int)(((unsigned short int *)(prd))[i+2])=0x0000;
+ (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl;
+ l -= 0x10000;
+ bttl += 0x10000;
+ i += 0x04;
+ }
+ (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x8000;
+ (unsigned short int)(((unsigned short int *)(prd))[i+2])=l;
+ (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl;
+ }
+ tmpcip=tmpcip+4;
+ prdaddru[h][tarid]=(unsigned long)&prd_tableu[h][tarid][0];
+ outl(prdaddru[h][tarid],tmpcip);
+ tmpcip=tmpcip-2;
+ outb(0x06,tmpcip);
+ outb(0x00,tmpcip);
+ tmpcip=tmpcip-2;
+ if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) ||
+ (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15))
+ {
+ dirctu[h][tarid]=0x20;
+ if ( inb(tmport) == 0 )
+ {
+ tmport=workportu+0x18;
+ outb(0x08,tmport);
+ outb(0x01,tmpcip);
+ }
+ else
+ {
+ last_cmd[h] |= 0x40;
+ }
+ in_snd[h]=0;
+ restore_flags(flags);
+ return;
+ }
+ if ( inb(tmport) == 0 )
+ {
+ tmport=workportu+0x18;
+ outb(0x08,tmport);
+ outb(0x09,tmpcip);
+ }
+ else
+ {
+ last_cmd[h] |= 0x40;
+ }
+ in_snd[h]=0;
+ restore_flags(flags);
+ return;
+
+}
+
+static void internal_done(Scsi_Cmnd * SCpnt)
+{
+ SCpnt->SCp.Status++;
+}
+
+int atp870u_command(Scsi_Cmnd * SCpnt)
+{
+
+ atp870u_queuecommand(SCpnt, internal_done);
+
+ SCpnt->SCp.Status = 0;
+ while (!SCpnt->SCp.Status)
+ barrier();
+ return SCpnt->result;
+}
+
+unsigned char fun_scam ( unsigned char host,unsigned short int * val )
+{
+ unsigned int tmport ;
+ unsigned short int i,k;
+ unsigned char j;
+
+ tmport = ioportu[host]+0x1c;
+ outw(*val,tmport);
+FUN_D7:
+ for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */
+ {
+ k=inw(tmport);
+ j= (unsigned char)(k >> 8);
+ if ((k & 0x8000) != 0) /* DB7 all release? */
+ {
+ goto FUN_D7;
+ }
+ }
+ *val |= 0x4000; /* assert DB6 */
+ outw(*val,tmport);
+ *val &= 0xdfff; /* assert DB5 */
+ outw(*val,tmport);
+FUN_D5:
+ for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */
+ {
+ if ((inw(tmport) & 0x2000) != 0) /* DB5 all release? */
+ {
+ goto FUN_D5;
+ }
+ }
+ *val |= 0x8000; /* no DB4-0, assert DB7 */
+ *val &= 0xe0ff;
+ outw(*val,tmport);
+ *val &= 0xbfff; /* release DB6 */
+ outw(*val,tmport);
+FUN_D6:
+ for ( i=0; i < 10; i++ ) /* stable >= bus settle delay(400 ns) */
+ {
+ if ((inw(tmport) & 0x4000) != 0) /* DB6 all release? */
+ {
+ goto FUN_D6;
+ }
+ }
+
+ return j;
+}
+
+void tscam( unsigned char host )
+{
+
+ unsigned int tmport ;
+ unsigned char i,j,k;
+ unsigned long n;
+ unsigned short int m,assignid_map,val;
+ unsigned char mbuf[33],quintet[2];
+ static unsigned char g2q_tab[8]={ 0x38,0x31,0x32,0x2b,0x34,0x2d,0x2e,0x27 };
+
+
+ for ( i=0; i < 0x10; i++ )
+ {
+ mydlyu(0xffff);
+ }
+
+ tmport = ioportu[host]+1;
+ outb(0x08,tmport++);
+ outb(0x7f,tmport);
+ tmport = ioportu[host]+0x11;
+ outb(0x20,tmport);
+
+ if ((scam_on[host] & 0x40) == 0)
+ {
+ return;
+ }
+
+ m=1;
+ m <<= host_idu[host];
+ j=16;
+ if ( chip_veru[host] < 4 )
+ {
+ m |= 0xff00;
+ j=8;
+ }
+ assignid_map=m;
+ tmport = ioportu[host]+0x02;
+ outb(0x02,tmport++); /* 2*2=4ms,3EH 2/32*3E=3.9ms */
+ outb(0,tmport++);
+ outb(0,tmport++);
+ outb(0,tmport++);
+ outb(0,tmport++);
+ outb(0,tmport++);
+ outb(0,tmport++);
+
+ for ( i = 0 ; i < j ; i ++ )
+ {
+ m=1;
+ m=m<<i;
+ if ( ( m & assignid_map ) != 0 )
+ {
+ continue;
+ }
+ tmport = ioportu[host]+0x0f;
+ outb(0,tmport++);
+ tmport += 0x02;
+ outb(0,tmport++);
+ outb(0,tmport++);
+ outb(0,tmport++);
+ if ( i > 7 )
+ {
+ k=(i & 0x07) | 0x40;
+ }
+ else
+ {
+ k=i;
+ }
+ outb(k,tmport++);
+ tmport = ioportu[host]+0x1b;
+ if ( chip_veru[host] == 4 )
+ {
+ outb((unsigned char)((inb(tmport) & 0x0e) | 0x01),tmport);
+ }
+ else
+ {
+ outb((unsigned char)(inb(tmport) & 0x0e),tmport);
+ }
+wait_rdyok:
+ tmport = ioportu[host]+0x18;
+ outb(0x09,tmport);
+ tmport += 0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport -= 0x08;
+ k=inb(tmport);
+ if ( k != 0x16 )
+ {
+ if ((k == 0x85) || (k == 0x42))
+ {
+ continue;
+ }
+ tmport = ioportu[host]+0x10;
+ outb(0x41,tmport);
+ goto wait_rdyok;
+ }
+ assignid_map |= m;
+
+ }
+ tmport = ioportu[host]+0x02;
+ outb(0x7f,tmport);
+ tmport = ioportu[host]+0x1b;
+ outb(0x02,tmport);
+
+ outb(0,0x80);
+
+ val=0x0080; /* bsy */
+ tmport = ioportu[host]+0x1c;
+ outw(val,tmport);
+ val |=0x0040; /* sel */
+ outw(val,tmport);
+ val |=0x0004; /* msg */
+ outw(val,tmport);
+ inb(0x80); /* 2 deskew delay(45ns*2=90ns) */
+ val &=0x007f; /* no bsy */
+ outw(val,tmport);
+ mydlyu(0xffff); /* recommanded SCAM selection response time */
+ mydlyu(0xffff);
+ val &=0x00fb; /* after 1ms no msg */
+ outw(val,tmport);
+wait_nomsg:
+ if ((inb(tmport) & 0x04) != 0)
+ {
+ goto wait_nomsg;
+ }
+ outb(1,0x80);
+ mydlyu(100);
+ for ( n=0; n < 0x30000; n++ )
+ {
+ if ((inb(tmport) & 0x80) != 0) /* bsy ? */
+ {
+ goto wait_io;
+ }
+ }
+ goto TCM_SYNC;
+wait_io:
+ for ( n=0; n < 0x30000; n++ )
+ {
+ if ((inb(tmport) & 0x81) == 0x0081)
+ {
+ goto wait_io1;
+ }
+ }
+ goto TCM_SYNC;
+wait_io1:
+ inb(0x80);
+ val |=0x8003; /* io,cd,db7 */
+ outw(val,tmport);
+ inb(0x80);
+ val &=0x00bf; /* no sel */
+ outw(val,tmport);
+ outb(2,0x80);
+TCM_SYNC:
+ mydlyu(0x800);
+ if ((inb(tmport) & 0x80) == 0x00) /* bsy ? */
+ {
+ outw(0,tmport--);
+ outb(0,tmport);
+ tmport=ioportu[host] + 0x15;
+ outb(0,tmport);
+ tmport += 0x03;
+ outb(0x09,tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0);
+ tmport -= 0x08;
+ inb(tmport);
+ return;
+ }
+
+ val &= 0x00ff; /* synchronization */
+ val |= 0x3f00;
+ fun_scam(host,&val);
+ outb(3,0x80);
+ val &= 0x00ff; /* isolation */
+ val |= 0x2000;
+ fun_scam(host,&val);
+ outb(4,0x80);
+ i=8;
+ j=0;
+TCM_ID:
+ if ((inw(tmport) & 0x2000) == 0)
+ {
+ goto TCM_ID;
+ }
+ outb(5,0x80);
+ val &= 0x00ff; /* get ID_STRING */
+ val |= 0x2000;
+ k=fun_scam(host,&val);
+ if ((k & 0x03) == 0)
+ {
+ goto TCM_5;
+ }
+ mbuf[j] <<= 0x01;
+ mbuf[j] &= 0xfe;
+ if ((k & 0x02) != 0)
+ {
+ mbuf[j] |= 0x01;
+ }
+ i--;
+ if ( i > 0 )
+ {
+ goto TCM_ID;
+ }
+ j++;
+ i=8;
+ goto TCM_ID;
+
+TCM_5: /* isolation complete.. */
+/* mbuf[32]=0;
+ printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
+ i=15;
+ j=mbuf[0];
+ if ((j & 0x20) != 0) /* bit5=1:ID upto 7 */
+ {
+ i=7;
+ }
+ if ((j & 0x06) == 0) /* IDvalid? */
+ {
+ goto G2Q5;
+ }
+ k=mbuf[1];
+small_id:
+ m=1;
+ m <<= k;
+ if ((m & assignid_map) == 0)
+ {
+ goto G2Q_QUIN;
+ }
+ if ( k > 0 )
+ {
+ k--;
+ goto small_id;
+ }
+G2Q5: /* srch from max acceptable ID# */
+ k=i; /* max acceptable ID# */
+G2Q_LP:
+ m=1;
+ m <<= k;
+ if ((m & assignid_map) == 0)
+ {
+ goto G2Q_QUIN;
+ }
+ if ( k > 0 )
+ {
+ k--;
+ goto G2Q_LP;
+ }
+G2Q_QUIN: /* k=binID#, */
+ assignid_map |= m;
+ if ( k < 8 )
+ {
+ quintet[0]=0x38; /* 1st dft ID<8 */
+ }
+ else
+ {
+ quintet[0]=0x31; /* 1st ID>=8 */
+ }
+ k &= 0x07;
+ quintet[1]=g2q_tab[k];
+
+ val &= 0x00ff; /* AssignID 1stQuintet,AH=001xxxxx */
+ m=quintet[0] << 8;
+ val |= m;
+ fun_scam(host,&val);
+ val &= 0x00ff; /* AssignID 2ndQuintet,AH=001xxxxx */
+ m=quintet[1] << 8;
+ val |= m;
+ fun_scam(host,&val);
+
+ goto TCM_SYNC;
+
+}
+
+void is870(unsigned long host,unsigned int wkport )
+{
+ unsigned int tmport ;
+ unsigned char i,j,k,rmb;
+ unsigned short int m;
+ static unsigned char mbuf[512];
+ static unsigned char satn[9] = { 0,0,0,0,0,0,0,6,6 };
+ static unsigned char inqd[9] = { 0x12,0,0,0,0x24,0,0,0x24,6 };
+ static unsigned char synn[6] = { 0x80,1,3,1,0x19,0x0e };
+ static unsigned char synu[6] = { 0x80,1,3,1,0x0c,0x0e };
+ static unsigned char synw[6] = { 0x80,1,3,1,0x0c,0x07 };
+ static unsigned char wide[6] = { 0x80,1,2,3,1,0 };
+
+ sync_idu=0;
+ tmport=wkport+0x3a;
+ outb((unsigned char)(inb(tmport) | 0x10),tmport);
+
+ for ( i = 0 ; i < 16 ; i ++ )
+ {
+ if ((chip_veru[host] != 4) && (i > 7))
+ {
+ break;
+ }
+ m=1;
+ m=m<<i;
+ if ( ( m & active_idu[host] ) != 0 )
+ {
+ continue;
+ }
+ if ( i == host_idu[host] )
+ {
+ printk(" ID: %2d Host Adapter\n",host_idu[host]);
+ continue;
+ }
+ if ( chip_veru[host] == 4 )
+ {
+ tmport=wkport+0x1b;
+ j=(inb(tmport) & 0x0e) | 0x01;
+ outb(j,tmport);
+ }
+ tmport=wkport+1;
+ outb(0x08,tmport++);
+ outb(0x7f,tmport++);
+ outb(satn[0],tmport++);
+ outb(satn[1],tmport++);
+ outb(satn[2],tmport++);
+ outb(satn[3],tmport++);
+ outb(satn[4],tmport++);
+ outb(satn[5],tmport++);
+ tmport+=0x06;
+ outb(0,tmport);
+ tmport+=0x02;
+ outb(devspu[host][i],tmport++);
+ outb(0,tmport++);
+ outb(satn[6],tmport++);
+ outb(satn[7],tmport++);
+ j=i;
+ if ((j & 0x08) != 0)
+ {
+ j=(j & 0x07) | 0x40;
+ }
+ outb(j,tmport);
+ tmport+=0x03;
+ outb(satn[8],tmport);
+ tmport+=0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+ {
+ continue;
+ }
+ while ( inb(tmport) != 0x8e );
+ active_idu[host] |= m;
+
+ tmport=wkport+0x10;
+ outb(0x30,tmport);
+ tmport=wkport+0x04;
+ outb(0x00,tmport);
+
+phase_cmd:
+ tmport=wkport+0x18;
+ outb(0x08,tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ j=inb(tmport);
+ if ( j != 0x16 )
+ {
+ tmport=wkport+0x10;
+ outb(0x41,tmport);
+ goto phase_cmd;
+ }
+sel_ok:
+ tmport=wkport+3;
+ outb(inqd[0],tmport++);
+ outb(inqd[1],tmport++);
+ outb(inqd[2],tmport++);
+ outb(inqd[3],tmport++);
+ outb(inqd[4],tmport++);
+ outb(inqd[5],tmport);
+ tmport+=0x07;
+ outb(0,tmport);
+ tmport+=0x02;
+ outb(devspu[host][i],tmport++);
+ outb(0,tmport++);
+ outb(inqd[6],tmport++);
+ outb(inqd[7],tmport++);
+ tmport+=0x03;
+ outb(inqd[8],tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+ {
+ continue;
+ }
+ while ( inb(tmport) != 0x8e );
+ if ( chip_veru[host] == 4 )
+ {
+ tmport=wkport+0x1b;
+ j=inb(tmport) & 0x0e;
+ outb(j,tmport);
+ }
+ tmport=wkport+0x18;
+ outb(0x08,tmport);
+ tmport += 0x07;
+ j=0;
+rd_inq_data:
+ k=inb(tmport);
+ if ((k & 0x01) != 0 )
+ {
+ tmport-=0x06;
+ mbuf[j++]=inb(tmport);
+ tmport+=0x06;
+ goto rd_inq_data;
+ }
+ if ((k & 0x80) == 0 )
+ {
+ goto rd_inq_data;
+ }
+ tmport-=0x08;
+ j=inb(tmport);
+ if ( j == 0x16 )
+ {
+ goto inq_ok;
+ }
+ tmport=wkport+0x10;
+ outb(0x46,tmport);
+ tmport+=0x02;
+ outb(0,tmport++);
+ outb(0,tmport++);
+ outb(0,tmport++);
+ tmport+=0x03;
+ outb(0x08,tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ if (inb(tmport) != 0x16)
+ {
+ goto sel_ok;
+ }
+inq_ok:
+ mbuf[36]=0;
+ printk(" ID: %2d %s\n",i,&mbuf[8]);
+ devtypeu[host][i]=mbuf[0];
+ rmb=mbuf[1];
+ if ( chip_veru[host] != 4 )
+ {
+ goto not_wide;
+ }
+ if ((mbuf[7] & 0x60) == 0)
+ {
+ goto not_wide;
+ }
+ if ((global_map[host] & 0x20) == 0)
+ {
+ goto not_wide;
+ }
+ tmport=wkport+0x1b;
+ j=(inb(tmport) & 0x0e) | 0x01;
+ outb(j,tmport);
+ tmport=wkport+3;
+ outb(satn[0],tmport++);
+ outb(satn[1],tmport++);
+ outb(satn[2],tmport++);
+ outb(satn[3],tmport++);
+ outb(satn[4],tmport++);
+ outb(satn[5],tmport++);
+ tmport+=0x06;
+ outb(0,tmport);
+ tmport+=0x02;
+ outb(devspu[host][i],tmport++);
+ outb(0,tmport++);
+ outb(satn[6],tmport++);
+ outb(satn[7],tmport++);
+ tmport+=0x03;
+ outb(satn[8],tmport);
+ tmport+=0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+ {
+ continue;
+ }
+ while ( inb(tmport) != 0x8e );
+try_wide:
+ j=0;
+ tmport=wkport+0x14;
+ outb(0x05,tmport);
+ tmport += 0x04;
+ outb(0x20,tmport);
+ tmport+=0x07;
+
+ while ((inb(tmport) & 0x80) == 0 )
+ {
+ if ((inb(tmport) & 0x01) != 0 )
+ {
+ tmport-=0x06;
+ outb(wide[j++],tmport);
+ tmport+=0x06;
+ }
+ }
+ tmport-=0x08;
+ while ((inb(tmport) & 0x80) == 0x00);
+ j=inb(tmport) & 0x0f;
+ if ( j == 0x0f )
+ {
+ goto widep_in;
+ }
+ if ( j == 0x0a )
+ {
+ goto widep_cmd;
+ }
+ if ( j == 0x0e )
+ {
+ goto try_wide;
+ }
+ continue;
+widep_out:
+ tmport=wkport+0x18;
+ outb(0x20,tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0 )
+ {
+ if ((inb(tmport) & 0x01) != 0 )
+ {
+ tmport-=0x06;
+ outb(0,tmport);
+ tmport+=0x06;
+ }
+ }
+ tmport-=0x08;
+ j=inb(tmport) & 0x0f;
+ if ( j == 0x0f )
+ {
+ goto widep_in;
+ }
+ if ( j == 0x0a )
+ {
+ goto widep_cmd;
+ }
+ if ( j == 0x0e )
+ {
+ goto widep_out;
+ }
+ continue;
+widep_in:
+ tmport=wkport+0x14;
+ outb(0xff,tmport);
+ tmport += 0x04;
+ outb(0x20,tmport);
+ tmport+=0x07;
+ k=0;
+widep_in1:
+ j=inb(tmport);
+ if ((j & 0x01) != 0)
+ {
+ tmport-=0x06;
+ mbuf[k++]=inb(tmport);
+ tmport+=0x06;
+ goto widep_in1;
+ }
+ if ((j & 0x80) == 0x00)
+ {
+ goto widep_in1;
+ }
+ tmport-=0x08;
+ j=inb(tmport) & 0x0f;
+ if ( j == 0x0f )
+ {
+ goto widep_in;
+ }
+ if ( j == 0x0a )
+ {
+ goto widep_cmd;
+ }
+ if ( j == 0x0e )
+ {
+ goto widep_out;
+ }
+ continue;
+widep_cmd:
+ tmport=wkport+0x10;
+ outb(0x30,tmport);
+ tmport=wkport+0x14;
+ outb(0x00,tmport);
+ tmport+=0x04;
+ outb(0x08,tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ j=inb(tmport);
+ if ( j != 0x16 )
+ {
+ if ( j == 0x4e )
+ {
+ goto widep_out;
+ }
+ continue;
+ }
+ if ( mbuf[0] != 0x01 )
+ {
+ goto not_wide;
+ }
+ if ( mbuf[1] != 0x02 )
+ {
+ goto not_wide;
+ }
+ if ( mbuf[2] != 0x03 )
+ {
+ goto not_wide;
+ }
+ if ( mbuf[3] != 0x01 )
+ {
+ goto not_wide;
+ }
+ m=1;
+ m = m << i;
+ wide_idu[host] |= m;
+not_wide:
+ if ((devtypeu[host][i] == 0x00) || (devtypeu[host][i] == 0x07))
+ {
+ goto set_sync;
+ }
+ continue;
+set_sync:
+ tmport=wkport+0x1b;
+ j=inb(tmport) & 0x0e;
+ if ((m & wide_idu[host]) != 0 )
+ {
+ j |= 0x01;
+ }
+ outb(j,tmport);
+ tmport=wkport+3;
+ outb(satn[0],tmport++);
+ outb(satn[1],tmport++);
+ outb(satn[2],tmport++);
+ outb(satn[3],tmport++);
+ outb(satn[4],tmport++);
+ outb(satn[5],tmport++);
+ tmport+=0x06;
+ outb(0,tmport);
+ tmport+=0x02;
+ outb(devspu[host][i],tmport++);
+ outb(0,tmport++);
+ outb(satn[6],tmport++);
+ outb(satn[7],tmport++);
+ tmport+=0x03;
+ outb(satn[8],tmport);
+ tmport+=0x07;
+
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+ {
+ continue;
+ }
+ while ( inb(tmport) != 0x8e);
+try_sync:
+ j=0;
+ tmport=wkport+0x14;
+ outb(0x06,tmport);
+ tmport += 0x04;
+ outb(0x20,tmport);
+ tmport+=0x07;
+
+ while ((inb(tmport) & 0x80) == 0 )
+ {
+ if ((inb(tmport) & 0x01) != 0 )
+ {
+ tmport-=0x06;
+ if ( rmb != 0 )
+ {
+ outb(synn[j++],tmport);
+ }
+ else
+ {
+ if ((m & wide_idu[host]) != 0)
+ {
+ outb(synw[j++],tmport);
+ }
+ else
+ {
+ if ((m & ultra_map[host]) != 0)
+ {
+ outb(synu[j++],tmport);
+ }
+ else
+ {
+ outb(synn[j++],tmport);
+ }
+ }
+ }
+ tmport+=0x06;
+ }
+ }
+ tmport-=0x08;
+ while ((inb(tmport) & 0x80) == 0x00);
+ j=inb(tmport) & 0x0f;
+ if ( j == 0x0f )
+ {
+ goto phase_ins;
+ }
+ if ( j == 0x0a )
+ {
+ goto phase_cmds;
+ }
+ if ( j == 0x0e )
+ {
+ goto try_sync;
+ }
+ continue;
+phase_outs:
+ tmport=wkport+0x18;
+ outb(0x20,tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0x00)
+ {
+ if ((inb(tmport) & 0x01) != 0x00)
+ {
+ tmport-=0x06;
+ outb(0x00,tmport);
+ tmport+=0x06;
+ }
+ }
+ tmport-=0x08;
+ j=inb(tmport);
+ if ( j == 0x85 )
+ {
+ goto tar_dcons;
+ }
+ j &= 0x0f;
+ if ( j == 0x0f )
+ {
+ goto phase_ins;
+ }
+ if ( j == 0x0a )
+ {
+ goto phase_cmds;
+ }
+ if ( j == 0x0e )
+ {
+ goto phase_outs;
+ }
+ continue;
+phase_ins:
+ tmport=wkport+0x14;
+ outb(0xff,tmport);
+ tmport += 0x04;
+ outb(0x20,tmport);
+ tmport+=0x07;
+ k=0;
+phase_ins1:
+ j=inb(tmport);
+ if ((j & 0x01) != 0x00)
+ {
+ tmport-=0x06;
+ mbuf[k++]=inb(tmport);
+ tmport+=0x06;
+ goto phase_ins1;
+ }
+ if ((j & 0x80) == 0x00)
+ {
+ goto phase_ins1;
+ }
+ tmport-=0x08;
+ while ((inb(tmport) & 0x80) == 0x00);
+ j=inb(tmport);
+ if ( j == 0x85 )
+ {
+ goto tar_dcons;
+ }
+ j &= 0x0f;
+ if ( j == 0x0f )
+ {
+ goto phase_ins;
+ }
+ if ( j == 0x0a )
+ {
+ goto phase_cmds;
+ }
+ if ( j == 0x0e )
+ {
+ goto phase_outs;
+ }
+ continue;
+phase_cmds:
+ tmport=wkport+0x10;
+ outb(0x30,tmport);
+tar_dcons:
+ tmport=wkport+0x14;
+ outb(0x00,tmport);
+ tmport+=0x04;
+ outb(0x08,tmport);
+ tmport+=0x07;
+ while ((inb(tmport) & 0x80) == 0x00);
+ tmport-=0x08;
+ j=inb(tmport);
+ if ( j != 0x16 )
+ {
+ continue;
+ }
+ if ( mbuf[0] != 0x01 )
+ {
+ continue;
+ }
+ if ( mbuf[1] != 0x03 )
+ {
+ continue;
+ }
+ if ( mbuf[4] == 0x00 )
+ {
+ continue;
+ }
+ if ( mbuf[3] > 0x64 )
+ {
+ continue;
+ }
+ if ( mbuf[4] > 0x0c )
+ {
+ mbuf[4]=0x0c;
+ }
+ devspu[host][i] = mbuf[4];
+ if ((mbuf[3] < 0x0d) && (rmb == 0))
+ {
+ j=0xa0;
+ goto set_syn_ok;
+ }
+ if ( mbuf[3] < 0x1a )
+ {
+ j=0x20;
+ goto set_syn_ok;
+ }
+ if ( mbuf[3] < 0x33 )
+ {
+ j=0x40;
+ goto set_syn_ok;
+ }
+ if ( mbuf[3] < 0x4c )
+ {
+ j=0x50;
+ goto set_syn_ok;
+ }
+ j=0x60;
+set_syn_ok:
+ devspu[host][i] = (devspu[host][i] & 0x0f) | j;
+ }
+ tmport=wkport+0x3a;
+ outb((unsigned char)(inb(tmport) & 0xef),tmport);
+}
+
+/* return non-zero on detection */
+int atp870u_detect(Scsi_Host_Template * tpnt)
+{
+ unsigned char irq,h,k;
+ unsigned long flags;
+ unsigned int base_io,error,tmport;
+ unsigned short index = 0;
+ unsigned char pci_bus[3], pci_device_fn[3], chip_ver[3],host_id;
+ struct Scsi_Host * shpnt = NULL;
+ int count = 0;
+ static unsigned short devid[7]={0x8002,0x8010,0x8020,0x8030,0x8040,0x8050,0};
+ static struct pci_dev *pdev = NULL;
+
+ printk("aec671x_detect: \n");
+ if (!pci_present())
+ {
+ printk(" NO BIOS32 SUPPORT.\n");
+ return count;
+ }
+
+ tpnt->proc_dir = &proc_scsi_atp870u;
+
+ for ( h = 0 ; h < 2 ; h++ )
+ {
+ active_idu[h]=0;
+ wide_idu[h]=0;
+ host_idu[h]=0x07;
+ quhdu[h]=0;
+ quendu[h]=0;
+ pci_bus[h]=0;
+ pci_device_fn[h]=0xff;
+ chip_ver[h]=0;
+ last_cmd[h]=0xff;
+ in_snd[h]=0;
+ in_int[h]=0;
+ for ( k = 0 ; k < qcnt ; k++ )
+ {
+ querequ[h][k]=0;
+ }
+ for ( k = 0 ; k < 16 ; k++ )
+ {
+ curr_req[h][k]=0;
+ }
+ }
+ h=0;
+ while ( devid[h] != 0 )
+ {
+ pci_find_device(0x1191,devid[h],pdev);
+ if (pdev == NULL); {
+ h++;
+ index=0;
+ continue;
+ }
+ chip_ver[2]=0;
+
+ /* To avoid messing with the things below... */
+ pci_device_fn[2] = pdev->devfn;
+ pci_bus[2] = pdev->bus->number;
+
+ if ( devid[h] == 0x8002 )
+ {
+ error = pci_read_config_byte(pdev,0x08,&chip_ver[2]);
+ if ( chip_ver[2] < 2 )
+ {
+ goto nxt_devfn;
+ }
+ }
+ if ( devid[h] == 0x8010 )
+ {
+ chip_ver[2]=0x04;
+ }
+ if ( pci_device_fn[2] < pci_device_fn[0] )
+ {
+ pci_bus[1]=pci_bus[0];
+ pci_device_fn[1]=pci_device_fn[0];
+ chip_ver[1]=chip_ver[0];
+ pci_bus[0]=pci_bus[2];
+ pci_device_fn[0]=pci_device_fn[2];
+ chip_ver[0]=chip_ver[2];
+ }
+ else if ( pci_device_fn[2] < pci_device_fn[1] )
+ {
+ pci_bus[1]=pci_bus[2];
+ pci_device_fn[1]=pci_device_fn[2];
+ chip_ver[1]=chip_ver[2];
+ }
+nxt_devfn:
+ index++;
+ if ( index > 3 )
+ {
+ index=0;
+ h++;
+ }
+ }
+ for ( h=0; h < 2; h++ )
+ {
+ if ( pci_device_fn[h] == 0xff )
+ {
+ return count;
+ }
+
+ pdev->devfn = pci_device_fn[h];
+ pdev->bus->number = pci_bus[h];
+
+ /* Found an atp870u/w. */
+ error = pci_read_config_dword(pdev,0x10,&base_io);
+ error += pci_read_config_byte(pdev,0x3c,&irq);
+ error += pci_read_config_byte(pdev,0x49,&host_id);
+
+ base_io &= 0xfffffff8;
+ printk(" ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d IO:%x, IRQ:%d.\n"
+ ,h,base_io,irq);
+ ioportu[h]=base_io;
+ pciportu[h]=base_io + 0x20;
+ irqnumu[h]=irq;
+ host_id &= 0x07;
+ host_idu[h]=host_id;
+ chip_veru[h]=chip_ver[h];
+
+ tmport=base_io+0x22;
+ scam_on[h]=inb(tmport);
+ tmport += 0x0b;
+ global_map[h]=inb(tmport++);
+ ultra_map[h]=inw(tmport);
+ if ( ultra_map[h] == 0 )
+ {
+ scam_on[h]=0x00;
+ global_map[h]=0x20;
+ ultra_map[h]=0xffff;
+ }
+
+ shpnt = scsi_register(tpnt,4);
+
+ save_flags(flags);
+ cli();
+ if (request_irq(irq,atp870u_intr_handle, 0, "atp870u", NULL))
+ {
+ printk("Unable to allocate IRQ for Acard controller.\n");
+ goto unregister;
+ }
+
+ tmport=base_io+0x3a;
+ k=(inb(tmport) & 0xf3) | 0x10;
+ outb(k,tmport);
+ outb((k & 0xdf),tmport);
+ mydlyu(0x8000);
+ outb(k,tmport);
+ mydlyu(0x8000);
+ tmport=base_io;
+ outb((host_id | 0x08),tmport);
+ tmport += 0x18;
+ outb(0,tmport);
+ tmport += 0x07;
+ while ((inb(tmport) & 0x80) == 0);
+ tmport -= 0x08;
+ inb(tmport);
+ tmport = base_io +1;
+ outb(8,tmport++);
+ outb(0x7f,tmport);
+ tmport = base_io + 0x11;
+ outb(0x20,tmport);
+
+ tscam(h);
+ is870(h,base_io);
+ tmport=base_io+0x3a;
+ outb((inb(tmport) & 0xef),tmport);
+
+ atp_host[h] = shpnt;
+ if ( chip_ver[h] == 4 )
+ {
+ shpnt->max_id = 16;
+ }
+ shpnt->this_id = host_id;
+ shpnt->unique_id = base_io;
+ shpnt->io_port = base_io;
+ shpnt->n_io_port = 0x40; /* Number of bytes of I/O space used */
+ shpnt->irq = irq;
+ restore_flags(flags);
+ request_region(base_io, 0x40,"atp870u"); /* Register the IO ports that we use */
+ count++;
+ index++;
+ continue;
+unregister:
+ scsi_unregister(shpnt);
+ restore_flags(flags);
+ index++;
+ continue;
+ }
+
+ return count;
+}
+
+/* The abort command does not leave the device in a clean state where
+ it is available to be used again. Until this gets worked out, we will
+ leave it commented out. */
+
+int atp870u_abort(Scsi_Cmnd * SCpnt)
+{
+ unsigned char h,j;
+ unsigned int tmport;
+/* printk(" atp870u_abort: \n"); */
+ for ( h=0; h <= admaxu; h++ )
+ {
+ if ( SCpnt->host == atp_host[h] )
+ {
+ goto find_adp;
+ }
+ }
+ panic("Abort host not found !");
+find_adp:
+ printk(" workingu=%x last_cmd=%x ",workingu[h],last_cmd[h]);
+ printk(" quhdu=%x quendu=%x ",quhdu[h],quendu[h]);
+ tmport=ioportu[h];
+ for ( j=0; j < 0x17; j++)
+ {
+ printk(" r%2x=%2x",j,inb(tmport++));
+ }
+ tmport += 0x05;
+ printk(" r1c=%2x",inb(tmport));
+ tmport += 0x03;
+ printk(" r1f=%2x in_snd=%2x ",inb(tmport),in_snd[h]);
+ tmport++;
+ printk(" r20=%2x",inb(tmport));
+ tmport += 0x02;
+ printk(" r22=%2x \n",inb(tmport));
+ return (SCSI_ABORT_SNOOZE);
+}
+
+int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+{
+ unsigned char h;
+ /*
+ * See if a bus reset was suggested.
+ */
+/* printk("atp870u_reset: \n"); */
+ for( h=0; h <= admaxu; h++ )
+ {
+ if ( SCpnt->host == atp_host[h] )
+ {
+ goto find_host;
+ }
+ }
+ panic("Reset bus host not found !");
+find_host:
+/* SCpnt->result = 0x00080000;
+ SCpnt->scsi_done(SCpnt);
+ workingu[h]=0;
+ quhdu[h]=0;
+ quendu[h]=0;
+ return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); */
+ return (SCSI_RESET_SNOOZE);
+}
+
+const char *
+atp870u_info(struct Scsi_Host *notused)
+{
+ static char buffer[128];
+
+ strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V1.0 ");
+
+ return buffer;
+}
+
+int
+atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+{
+ return (-ENOSYS); /* Currently this is a no-op */
+}
+
+#define BLS buffer + len + size
+int
+atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
+ int hostno, int inout)
+{
+ struct Scsi_Host *HBAptr;
+ static u8 buff[512];
+ int i;
+ int size = 0;
+ int len = 0;
+ off_t begin = 0;
+ off_t pos = 0;
+
+ HBAptr = NULL;
+ for (i = 0; i < 2; i++)
+ {
+ if ((HBAptr = atp_host[i]) != NULL)
+ {
+ if (HBAptr->host_no == hostno)
+ {
+ break;
+ }
+ HBAptr = NULL;
+ }
+ }
+
+ if (HBAptr == NULL)
+ {
+ size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
+ len += size; pos = begin + len; size = 0;
+ goto stop_output;
+ }
+
+ if (inout == TRUE) /* Has data been written to the file? */
+ {
+ return (atp870u_set_info(buffer, length, HBAptr));
+ }
+
+ if (offset == 0)
+ {
+ memset(buff, 0, sizeof(buff));
+ }
+
+ size += sprintf(BLS, "ACARD AEC-671X Driver Version: 1.0\n");
+ len += size; pos = begin + len; size = 0;
+
+ size += sprintf(BLS, "\n");
+ size += sprintf(BLS, "Adapter Configuration:\n");
+ size += sprintf(BLS, " Base IO: %#.4lx\n", HBAptr->io_port);
+ size += sprintf(BLS, " IRQ: %d\n", HBAptr->irq);
+ len += size; pos = begin + len; size = 0;
+
+stop_output:
+ *start = buffer + (offset - begin); /* Start of wanted data */
+ len -= (offset - begin); /* Start slop */
+ if (len > length)
+ {
+ len = length; /* Ending slop */
+ }
+
+ return (len);
+}
+
+#include "sd.h"
+
+int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int * ip)
+{
+ int heads, sectors, cylinders;
+
+ heads = 64;
+ sectors = 32;
+ cylinders = disk->capacity / (heads * sectors);
+
+ if ( cylinders > 1024 )
+ {
+ heads = 255;
+ sectors = 63;
+ cylinders = disk->capacity / (heads * sectors);
+ }
+
+ ip[0] = heads;
+ ip[1] = sectors;
+ ip[2] = cylinders;
+
+ return 0;
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = ATP870U;
+
+#include "scsi_module.c"
+#endif
+
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
new file mode 100644
index 000000000..64cb56b9e
--- /dev/null
+++ b/drivers/scsi/atp870u.h
@@ -0,0 +1,72 @@
+#ifndef _ATP870U_H
+
+/* $Id: atp870u.h,v 1.0 1997/05/07 15:09:00 root Exp root $
+ *
+ * Header file for the ACARD 870U/W driver for Linux
+ *
+ * $Log: atp870u.h,v $
+ * Revision 1.0 1997/05/07 15:09:00 root
+ * Initial revision
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+
+/* I/O Port */
+
+#define MAX_CDB 12
+#define MAX_SENSE 14
+
+int atp870u_detect(Scsi_Host_Template *);
+int atp870u_command(Scsi_Cmnd *);
+int atp870u_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int atp870u_abort(Scsi_Cmnd *);
+int atp870u_reset(Scsi_Cmnd *, unsigned int);
+int atp870u_biosparam(Disk *, kdev_t, int*);
+void send_s870(unsigned char);
+
+#define qcnt 32
+#define ATP870U_SCATTER 127
+#define ATP870U_CMDLUN 1
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+extern struct proc_dir_entry proc_scsi_atp870u;
+
+extern const char *atp870u_info(struct Scsi_Host *);
+
+extern int atp870u_proc_info(char *, char **, off_t, int, int, int);
+
+#define ATP870U { \
+ next: NULL, \
+ module: NULL, \
+ proc_dir: &proc_scsi_atp870u, \
+ proc_info: atp870u_proc_info, \
+ name: NULL, \
+ detect: atp870u_detect, \
+ release: NULL, \
+ info: atp870u_info, \
+ command: atp870u_command, \
+ queuecommand: atp870u_queuecommand, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: atp870u_abort, \
+ reset: atp870u_reset, \
+ slave_attach: NULL, \
+ bios_param: atp870u_biosparam, \
+ can_queue: qcnt, \
+ this_id: 1, \
+ sg_tablesize: ATP870U_SCATTER, \
+ cmd_per_lun: ATP870U_CMDLUN, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: ENABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+}
+#endif
diff --git a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h
index b3a30ebe0..02ed19d4d 100644
--- a/drivers/scsi/dc390.h
+++ b/drivers/scsi/dc390.h
@@ -4,7 +4,7 @@
* Description: Device Driver for Tekram DC-390(T) PCI SCSI *
* Bus Master Host Adapter *
***********************************************************************/
-/* $Id: dc390.h,v 2.3 1998/10/24 08:45:02 garloff Exp $ */
+/* $Id: dc390.h,v 1.3 1999/01/04 16:06:59 ralf Exp $ */
#include <linux/version.h>
@@ -16,7 +16,7 @@
#define DC390_H
#define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.0b 1998/10/24"
+#define DC390_VERSION "2.0d 1998/12/25"
#if defined(HOSTS_C) || defined(MODULE)
diff --git a/drivers/scsi/eata_dma.c b/drivers/scsi/eata_dma.c
index 68c195c7e..5542e8fa5 100644
--- a/drivers/scsi/eata_dma.c
+++ b/drivers/scsi/eata_dma.c
@@ -963,7 +963,7 @@ char * get_board_data(u32 base, u32 irq, u32 id)
eata_send_command((u32) cp, (u32) base, EATA_CMD_DMA_SEND_CP);
i = jiffies + (3 * HZ);
- while (fake_int_happened == FALSE && jiffies <= i)
+ while (fake_int_happened == FALSE && time_before_eq(jiffies, i))
barrier();
DBG(DBG_INTR3, printk(KERN_DEBUG "fake_int_result: %#x hbastat %#x "
@@ -974,7 +974,7 @@ char * get_board_data(u32 base, u32 irq, u32 id)
scsi_init_free((void *)cp, sizeof(struct eata_ccb));
scsi_init_free((void *)sp, sizeof(struct eata_sp));
- if ((fake_int_result & HA_SERROR) || jiffies > i){
+ if ((fake_int_result & HA_SERROR) || time_after(jiffies, i)){
printk(KERN_WARNING "eata_dma: trying to reset HBA at %x to clear "
"possible blink state\n", base);
/* hard reset the HBA */
diff --git a/drivers/scsi/eata_dma_proc.c b/drivers/scsi/eata_dma_proc.c
index 267d8bf82..15aa4d9fa 100644
--- a/drivers/scsi/eata_dma_proc.c
+++ b/drivers/scsi/eata_dma_proc.c
@@ -1,4 +1,3 @@
-
void swap_statistics(u8 *p)
{
u32 y;
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index d35c32d07..a706a8e7f 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -500,7 +500,7 @@ int eata_pio_reset(Scsi_Cmnd * cmd, unsigned int dummy)
HD(cmd)->state = RESET;
time = jiffies;
- while (jiffies < (time + (3 * HZ)) && limit++ < 10000000);
+ while (time_before(jiffies, time + 3 * HZ) && limit++ < 10000000);
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, "
"loops %d.\n", limit));
diff --git a/drivers/scsi/eata_pio_proc.c b/drivers/scsi/eata_pio_proc.c
index 829053315..a6c59d7c6 100644
--- a/drivers/scsi/eata_pio_proc.c
+++ b/drivers/scsi/eata_pio_proc.c
@@ -24,7 +24,6 @@ int eata_pio_set_info(char *buffer, int length, struct Scsi_Host *HBA_ptr)
int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length,
int hostno, int inout)
{
-
Scsi_Device *scd;
struct Scsi_Host *HBA_ptr;
static u8 buff[512];
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index f17f0bdd5..aaa23937a 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -472,11 +472,9 @@ int fd_mcs_detect( Scsi_Host_Template *tpnt )
/* *************************************************** */
#endif
-#if 0
/* IBM/ANSI scsi scan ordering */
/* Stick this back in when the scsi.c changes are there */
- shpnt->reverse_scan = 1;
-#endif
+ shpnt->reverse_ordering = 1;
/* saving info */
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 3c26b4557..760b3fbc5 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1,10 +1,8 @@
/* fdomain.c -- Future Domain TMC-16x0 SCSI driver
* Created: Sun May 3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Wed Oct 2 11:10:55 1996 by faith@acm.org
+ * Revised: Mon Dec 28 21:59:02 1998 by faith@acm.org
* Author: Rickard E. Faith, faith@cs.unc.edu
- * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
- *
- * Version 5.46 (23-04-1998)
+ * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org)
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -32,13 +30,34 @@
Future Domain TMC-1650, TMC-1660, TMC-1670, TMC-1680, TMC-1610M/MER/MEX
Future Domain TMC-3260 (PCI)
Quantum ISA-200S, ISA-250MG
- Adaptec AHA-2920 (PCI)
+ Adaptec AHA-2920A (PCI) [BUT *NOT* AHA-2920C -- use aic7xxx instead]
IBM ?
- LILO command-line options:
+ LILO/INSMOD command-line options:
fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]
+
+ NOTE:
+
+ The Adaptec AHA-2920C has an Adaptec AIC-7850 chip on it.
+ Use the aic7xxx driver for this board.
+
+ The Adaptec AHA-2920A has a Future Domain chip on it, so this is the right
+ driver for that card. Unfortunately, the boxes will probably just say
+ "2920", so you'll have to look on the card for a Future Domain logo, or a
+ letter after the 2920.
+
+
+
+ THANKS:
+
+ Thanks to Adaptec for providing PCI boards for testing. This finally
+ enabled me to test the PCI detection and correct it for PCI boards that do
+ not have a BIOS at a standard ISA location. For PCI boards, LILO/INSMOD
+ command-line options should no longer be needed. --RF 18Nov98
+
+
DESCRIPTION:
This is the Linux low-level SCSI driver for Future Domain TMC-1660/1680
@@ -70,7 +89,7 @@
your board. Please refer to the Seagate driver for more information and
possible support.
-
+
HISTORY:
@@ -108,7 +127,8 @@
2.1.1 5.45 2 Oct 1996 Update ROM accesses for 2.1.x
2.1.97 5.46 23 Apr 1998 Rewritten PCI detection routines [mj]
2.1.11x 5.47 9 Aug 1998 Touched for 8 SCSI disk majors support
-
+ 5.48 18 Nov 1998 BIOS no longer needed for PCI detection
+ 2.2.0 5.50 28 Dec 1998 Support insmod parameters
REFERENCES USED:
@@ -207,6 +227,9 @@
patches.
New PCI detection code written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+
+ Insmod parameter code based on patches from Daniel Graham
+ <graham@balance.uoregon.edu>.
All of the alpha testers deserve much thanks.
@@ -282,7 +305,7 @@ struct proc_dir_entry proc_scsi_fdomain = {
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
-#define VERSION "$Revision: 5.45 $"
+#define VERSION "$Revision: 5.50 $"
/* START OF USER DEFINABLE OPTIONS */
@@ -406,6 +429,15 @@ static int FIFO_Size = 0x2000; /* 8k FIFO for
extern void do_fdomain_16x0_intr( int irq, void *dev_id,
struct pt_regs * regs );
+#ifdef MODULE
+ /* Allow insmod parameters to be like LILO
+ parameters. For example:
+ insmod fdomain fdomain=0x140,11
+ */
+static int fdomain[]={ 0, 0, 0 };
+MODULE_PARM(fdomain, "2-3i");
+#endif
+
static unsigned long addresses[] = {
0xc8000,
0xca000,
@@ -504,10 +536,10 @@ static void print_banner( struct Scsi_Host *shpnt )
if (!shpnt) return; /* This won't ever happen */
if (bios_major < 0 && bios_minor < 0) {
- printk( "scsi%d <fdomain>: No BIOS; using scsi id %d\n",
+ printk( "scsi%d: <fdomain> No BIOS; using scsi id %d\n",
shpnt->host_no, shpnt->this_id );
} else {
- printk( "scsi%d <fdomain>: BIOS version ", shpnt->host_no );
+ printk( "scsi%d: <fdomain> BIOS version ", shpnt->host_no );
if (bios_major >= 0) printk( "%d.", bios_major );
else printk( "?." );
@@ -523,7 +555,7 @@ static void print_banner( struct Scsi_Host *shpnt )
boards, we will have to modify banner
for additional PCI cards, but for now if
it's PCI it's a TMC-3260 - JTM */
- printk( "scsi%d <fdomain>: %s chip at 0x%x irq ",
+ printk( "scsi%d: <fdomain> %s chip at 0x%x irq ",
shpnt->host_no,
chip == tmc1800 ? "TMC-1800"
: (chip == tmc18c50 ? "TMC-18C50"
@@ -541,8 +573,9 @@ static void print_banner( struct Scsi_Host *shpnt )
void fdomain_setup( char *str, int *ints )
{
if (setup_called++ || ints[0] < 2 || ints[0] > 3) {
- printk( "fdomain: usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
- printk( "fdomain: bad LILO parameters?\n" );
+ printk( "scsi: <fdomain>"
+ " Usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n" );
+ printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
}
port_base = ints[0] >= 1 ? ints[1] : 0;
@@ -591,8 +624,6 @@ static int fdomain_is_valid_port( int port )
if (inb( port + MSB_ID_Code ) != 0x60) return 0;
chip = tmc18c50;
-#if 1
-
/* Try to toggle 32-bit mode. This only
works on an 18c30 chip. (User reports
say this works, so we should switch to
@@ -606,17 +637,6 @@ static int fdomain_is_valid_port( int port )
FIFO_Size = 0x800; /* 2k FIFO */
}
}
-#else
-
- /* That should have worked, but appears to
- have problems. Let's assume it is an
- 18c30 if the RAM is disabled. */
-
- if (inb( port + Configuration2 ) & 0x02) {
- chip = tmc18c30;
- FIFO_Size = 0x800; /* 2k FIFO */
- }
-#endif
/* If that failed, we are an 18c50. */
}
@@ -656,7 +676,7 @@ static int fdomain_get_irq( int base )
int options = inb( base + Configuration1 );
#if DEBUG_DETECT
- printk( " Options = %x\n", options );
+ printk( "scsi: <fdomain> Options = %x\n", options );
#endif
/* Check for board with lowest bios_base --
@@ -673,10 +693,31 @@ static int fdomain_get_irq( int base )
static int fdomain_isa_detect( int *irq, int *iobase )
{
- int i;
+ int i, j;
int base;
int flag = 0;
+#if DEBUG_DETECT
+ printk( "scsi: <fdomain> fdomain_isa_detect:" );
+#endif
+
+ for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
+#if DEBUG_DETECT
+ printk( " %lx(%lx),", addresses[i], bios_base );
+#endif
+ for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
+ if (check_signature(addresses[i] + signatures[j].sig_offset,
+ signatures[j].signature,
+ signatures[j].sig_length )) {
+ bios_major = signatures[j].major_bios_version;
+ bios_minor = signatures[j].minor_bios_version;
+ PCI_bus = (signatures[j].flag == 1);
+ Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
+ bios_base = addresses[i];
+ }
+ }
+ }
+
if (bios_major == 2) {
/* The TMC-1660/TMC-1680 has a RAM area just after the BIOS ROM.
Assuming the ROM is enabled (otherwise we wouldn't have been
@@ -746,6 +787,11 @@ static int fdomain_isa_detect( int *irq, int *iobase )
if ((flag = fdomain_is_valid_port( base ))) break;
}
+#if DEBUG_DETECT
+ if (flag) printk( " SUCCESS\n" );
+ else printk( " FAILURE\n" );
+#endif
+
if (!flag) return 0; /* iobase not found */
*irq = fdomain_get_irq( base );
@@ -771,18 +817,21 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase )
/* Tell how to print a list of the known PCI devices from bios32 and
list vendor and device IDs being used if in debug mode. */
- printk( "\nINFO: use lspci -v to see list of PCI devices\n" );
- printk( "\nTMC-3260 detect:"
- " Using PCI Vendor ID: 0x%x, PCI Device ID: 0x%x\n",
+ printk( "scsi: <fdomain> INFO: use lspci -v to see list of PCI devices\n" );
+ printk( "scsi: <fdomain> TMC-3260 detect:"
+ " Using Vendor ID: 0x%x and Device ID: 0x%x\n",
PCI_VENDOR_ID_FD,
PCI_DEVICE_ID_FD_36C70 );
#endif
- if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL)
+ if ((pdev = pci_find_device(PCI_VENDOR_ID_FD,
+ PCI_DEVICE_ID_FD_36C70,
+ pdev)) == NULL)
return 0;
#if DEBUG_DETECT
- printk( "Future Domain 36C70 : at PCI bus %u, device %u, function %u\n",
+ printk( "scsi: <fdomain> TMC-3260 detect:"
+ " PCI bus %u, device %u, function %u\n",
pdev->bus->number,
PCI_SLOT(pdev->devfn),
PCI_FUNC(pdev->devfn));
@@ -793,10 +842,6 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase )
pci_base = pdev->base_address[0];
pci_irq = pdev->irq;
-#if DEBUG_DETECT
- printk( "TMC-3260 PCI: IRQ = %u, I/O base = 0x%lx\n",
- pci_irq, pci_base );
-#endif
/* Now we have the I/O base address and interrupt from the PCI
configuration registers. */
@@ -805,18 +850,28 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase )
*iobase = (pci_base & PCI_BASE_ADDRESS_IO_MASK);
#if DEBUG_DETECT
- printk( "TMC-3260 fix: Masking I/O base address with 0xff00.\n" );
- printk( "TMC-3260: IRQ = %d, I/O base = 0x%x\n", *irq, *iobase );
+ printk( "scsi: <fdomain> TMC-3260 detect:"
+ " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
#endif
- if (!fdomain_is_valid_port( *iobase )) return 0;
+ if (!fdomain_is_valid_port( *iobase )) {
+ printk( "scsi: <fdomain>"
+ " PCI card detected, but driver not loaded (invalid port)\n" );
+ return 0;
+ }
+
+ /* Fill in a few global variables. Ugh. */
+ bios_major = bios_minor = -1;
+ PCI_bus = 1;
+ Quantum = 0;
+ bios_base = 0;
+
return 1;
}
#endif
int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
{
- int i, j;
int retcode;
struct Scsi_Host *shpnt;
#if DO_DETECT
@@ -829,68 +884,44 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
unsigned char buf[buflen];
#endif
-#if DEBUG_DETECT
- printk( "fdomain_16x0_detect()," );
-#endif
tpnt->proc_dir = &proc_scsi_fdomain;
+#ifdef MODULE
+ if (fdomain[0] || fdomain[1] || fdomain[2]) {
+ port_base = fdomain[0];
+ interrupt_level = fdomain[1];
+ this_id = fdomain[2];
+ bios_major = bios_minor = -1;
+ ++setup_called;
+ }
+#endif
+
if (setup_called) {
#if DEBUG_DETECT
- printk( "no BIOS, using port_base = 0x%x, irq = %d\n",
+ printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
port_base, interrupt_level );
#endif
if (!fdomain_is_valid_port( port_base )) {
- printk( "fdomain: cannot locate chip at port base 0x%x\n",
+ printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
port_base );
- printk( "fdomain: bad LILO parameters?\n" );
+ printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
return 0;
}
} else {
int flag = 0;
-
- for (i = 0; !bios_base && i < ADDRESS_COUNT; i++) {
-#if DEBUG_DETECT
- printk( " %lx(%lx),", addresses[i], bios_base );
-#endif
- for (j = 0; !bios_base && j < SIGNATURE_COUNT; j++) {
- if (check_signature(addresses[i] + signatures[j].sig_offset,
- signatures[j].signature,
- signatures[j].sig_length )) {
- bios_major = signatures[j].major_bios_version;
- bios_minor = signatures[j].minor_bios_version;
- PCI_bus = (signatures[j].flag == 1);
- Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
- bios_base = addresses[i];
- }
- }
- }
-
- if (!bios_base) {
-#if DEBUG_DETECT
- printk( " FAILED: NO BIOS\n" );
-#endif
- return 0;
- }
- if (!PCI_bus) {
- flag = fdomain_isa_detect( &interrupt_level, &port_base );
- } else {
#ifdef CONFIG_PCI
- flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
-#else
- printk(KERN_ERR "No PCI support in this kernel, giving up.\n");
- flag = 0;
+ /* Try PCI detection first */
+ flag = fdomain_pci_bios_detect( &interrupt_level, &port_base );
#endif
- }
-
if (!flag) {
-#if DEBUG_DETECT
- printk( " FAILED: NO PORT\n" );
-#endif
-#ifdef CONFIG_PCI
- printk( "\nTMC-3260 36C70 PCI scsi chip detection failed.\n" );
-#endif
- return 0; /* Cannot find valid set of ports */
+ /* Then try ISA bus detection */
+ flag = fdomain_isa_detect( &interrupt_level, &port_base );
+
+ if (!flag) {
+ printk( "scsi: <fdomain> Detection failed (no card)\n" );
+ return 0;
+ }
}
}
@@ -911,13 +942,10 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
fdomain_16x0_reset( NULL, 0 );
if (fdomain_test_loopback()) {
-#if DEBUG_DETECT
- printk( "fdomain: LOOPBACK TEST FAILED, FAILING DETECT!\n" );
-#endif
+ printk( "scsi: <fdomain> Detection failed"
+ " (loopback test failed at port base 0x%x)\n", port_base );
if (setup_called) {
- printk( "fdomain: loopback test failed at port base 0x%x\n",
- port_base );
- printk( "fdomain: bad LILO parameters?\n" );
+ printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
}
return 0;
}
@@ -946,7 +974,9 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
/* Log IRQ with kernel */
if (!interrupt_level) {
- panic( "fdomain: *NO* interrupt level selected!\n" );
+ printk( "scsi: <fdomain>"
+ " Card Detected, but driver not loaded (no IRQ)\n" );
+ return 0;
} else {
/* Register the IRQ with the kernel */
@@ -955,18 +985,21 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
if (retcode < 0) {
if (retcode == -EINVAL) {
- printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
- printk( " This shouldn't happen!\n" );
- printk( " Send mail to faith@acm.org\n" );
+ printk( "scsi: <fdomain> IRQ %d is bad!\n", interrupt_level );
+ printk( " This shouldn't happen!\n" );
+ printk( " Send mail to faith@acm.org\n" );
} else if (retcode == -EBUSY) {
- printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
- printk( " Please use another IRQ!\n" );
+ printk( "scsi: <fdomain> IRQ %d is already in use!\n",
+ interrupt_level );
+ printk( " Please use another IRQ!\n" );
} else {
- printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
- printk( " This shouldn't happen!\n" );
- printk( " Send mail to faith@acm.org\n" );
+ printk( "scsi: <fdomain> Error getting IRQ %d\n",
+ interrupt_level );
+ printk( " This shouldn't happen!\n" );
+ printk( " Send mail to faith@acm.org\n" );
}
- panic( "fdomain: Driver requires interruptions\n" );
+ printk( "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
+ return 0;
}
}
@@ -987,7 +1020,7 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
SCinit.use_sg = 0;
SCinit.lun = 0;
- printk( "fdomain: detection routine scanning for devices:\n" );
+ printk( "scsi: <fdomain> detection routine scanning for devices:\n" );
for (i = 0; i < 8; i++) {
SCinit.target = i;
if (i == tpnt->this_id) /* Skip host adapter */
@@ -1031,10 +1064,10 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
const char *fdomain_16x0_info( struct Scsi_Host *ignore )
{
- static char buffer[80];
+ static char buffer[128];
char *pt;
- strcpy( buffer, "Future Domain TMC-16x0 SCSI driver, version" );
+ strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" );
if (strchr( VERSION, ':')) { /* Assume VERSION is an RCS Revision string */
strcat( buffer, strchr( VERSION, ':' ) + 1 );
pt = strrchr( buffer, '$') - 1;
@@ -1118,7 +1151,7 @@ static int fdomain_arbitrate( void )
printk( "Arbitration failed, status = %x\n", status );
#endif
#if ERRORS_ONLY
- printk( "fdomain: Arbitration failed, status = %x\n", status );
+ printk( "scsi: <fdomain> Arbitration failed, status = %x\n", status );
#endif
return 1;
}
@@ -1158,7 +1191,7 @@ static int fdomain_select( int target )
if (!flag) /* Skip first failure for all chips. */
++flag;
else
- printk( "fdomain: Selection failed\n" );
+ printk( "scsi: <fdomain> Selection failed\n" );
}
#endif
return 1;
@@ -1173,9 +1206,9 @@ void my_done( int error )
current_SC->result = error;
if (current_SC->scsi_done)
current_SC->scsi_done( current_SC );
- else panic( "fdomain: current_SC->scsi_done() == NULL" );
+ else panic( "scsi: <fdomain> current_SC->scsi_done() == NULL" );
} else {
- panic( "fdomain: my_done() called outside of command\n" );
+ panic( "scsi: <fdomain> my_done() called outside of command\n" );
}
#if DEBUG_RACE
in_interrupt_flag = 0;
@@ -1211,7 +1244,7 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
/* Abort calls my_done, so we do nothing here. */
if (current_SC->SCp.phase & aborted) {
#if DEBUG_ABORT
- printk( "Interrupt after abort, ignoring\n" );
+ printk( "scsi: <fdomain> Interrupt after abort, ignoring\n" );
#endif
/*
return; */
@@ -1311,7 +1344,7 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
if (current_SC->SCp.Status
&& current_SC->SCp.Status != 2
&& current_SC->SCp.Status != 8) {
- printk( "fdomain: target = %d, command = %x, status = %x\n",
+ printk( "scsi: <fdomain> target = %d, command = %x, status = %x\n",
current_SC->target,
current_SC->cmnd[0],
current_SC->SCp.Status );
@@ -1329,7 +1362,8 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
if (!current_SC->SCp.Message) ++done;
#if DEBUG_MESSAGES || EVERY_ACCESS
if (current_SC->SCp.Message) {
- printk( "fdomain: message = %x\n", current_SC->SCp.Message );
+ printk( "scsi: <fdomain> message = %x\n",
+ current_SC->SCp.Message );
}
#endif
break;
@@ -1590,8 +1624,8 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
|| code == 0x24
|| !code)))
- printk( "fdomain: REQUEST SENSE "
- "Key = %x, Code = %x, Qualifier = %x\n",
+ printk( "scsi: <fdomain> REQUEST SENSE"
+ " Key = %x, Code = %x, Qualifier = %x\n",
key, code, qualifier );
}
}
@@ -1624,7 +1658,7 @@ void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs )
int fdomain_16x0_queue( Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
{
if (in_command) {
- panic( "fdomain: fdomain_16x0_queue() NOT REENTRANT!\n" );
+ panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
}
#if EVERY_ACCESS
printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
@@ -1704,7 +1738,8 @@ void print_info( Scsi_Cmnd *SCpnt )
unsigned int isr;
if (!SCpnt || !SCpnt->host) {
- printk( "fdomain: cannot provide detailed information\n" );
+ printk( "scsi: <fdomain> Cannot provide detailed information\n" );
+ return;
}
printk( "%s\n", fdomain_16x0_info( SCpnt->host ) );
@@ -1770,7 +1805,7 @@ int fdomain_16x0_abort( Scsi_Cmnd *SCpnt)
{
unsigned long flags;
#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
- printk( "fdomain: abort " );
+ printk( "scsi: <fdomain> abort " );
#endif
save_flags( flags );
@@ -1808,7 +1843,7 @@ int fdomain_16x0_reset( Scsi_Cmnd *SCpnt, unsigned int ignored )
#endif
#if ERRORS_ONLY
- if (SCpnt) printk( "fdomain: SCSI Bus Reset\n" );
+ if (SCpnt) printk( "scsi: <fdomain> SCSI Bus Reset\n" );
#endif
#if DEBUG_RESET
@@ -1893,7 +1928,7 @@ int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
*/
if (MAJOR(dev) != SCSI_DISK0_MAJOR) {
- printk("fdomain_16x0_biosparam: too many disks");
+ printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
return 0;
}
drive = MINOR(dev) >> 4;
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index d8c0c9e0d..ec1f6edc8 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -495,7 +495,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
dst[start+i] = NCR5380_read(C400_HOST_BUFFER);
#else
/* implies CONFIG_SCSI_G_NCR5380_MEM */
- memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
+ memcpy(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
#endif
start+=128;
blocks--;
@@ -516,7 +516,7 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
dst[start+i] = NCR5380_read(C400_HOST_BUFFER);
#else
/* implies CONFIG_SCSI_G_NCR5380_MEM */
- memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
+ memcpy(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
#endif
start+=128;
blocks--;
@@ -603,7 +603,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
NCR5380_write(C400_HOST_BUFFER, src[start+i]);
#else
/* implies CONFIG_SCSI_G_NCR5380_MEM */
- memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
+ memcpy(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
#endif
start+=128;
blocks--;
@@ -623,7 +623,7 @@ static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src
NCR5380_write(C400_HOST_BUFFER, src[start+i]);
#else
/* implies CONFIG_SCSI_G_NCR5380_MEM */
- memmove(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
+ memcpy(NCR53C400_host_buffer+NCR5380_map_name,src+start,128);
#endif
start+=128;
blocks--;
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index 18a864155..3bc53d5b2 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -2,7 +2,7 @@
* GDT ISA/EISA/PCI Disk Array Controller driver for Linux *
* *
* gdth.c *
- * Copyright (C) 1995-97 ICP vortex Computersysteme GmbH, Achim Leubner *
+ * Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner *
* *
* <achim@vortex.de> *
* *
@@ -20,27 +20,49 @@
* along with this kernel; if not, write to the Free Software *
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
* *
- * Tested with Linux 1.2.13, ..., 2.1.61 *
+ * Tested with Linux 1.2.13, ..., 2.1.131 *
* *
* $Log: gdth.c,v $
- * Revision 1.3 1998/02/25 23:52:32 ecd
- * Final round of PCI device driver patches by Martin Mares.
+ * Revision 1.17 1998/12/17 15:58:11 achim
+ * Command line parameters implemented
+ * Changes for Alpha platforms
+ * PCI controller scan changed
+ * SMP support improved (spin_lock_irqsave(),...)
+ * New async. events, new scan/reserve commands included
*
- * I could not verify each and every change to the drivers locally,
- * please consult linux/Documentation/pci.txt to understand changes
- * made in case patching should be necessary.
+ * Revision 1.16 1998/09/28 16:08:46 achim
+ * GDT_PCIMPR: DPMEM remapping, if required
+ * mdelay() added
*
- * Revision 1.2 1997/11/12 23:58:51 davem
- * Merge to 2.1.63 to get the Ingo P5 bugfix.
- * I did not touch the sound changes at all, Alan
- * please look into that stuff as it is your
- * territory.
+ * Revision 1.15 1998/06/03 14:54:06 achim
+ * gdth_delay(), gdth_flush() implemented
+ * Bugfix: gdth_release() changed
+ *
+ * Revision 1.14 1998/05/22 10:01:17 achim
+ * mj: pcibios_strerror() removed
+ * Improved SMP support (if version >= 2.1.95)
+ * gdth_halt(): halt_called flag added (if version < 2.1)
+ *
+ * Revision 1.13 1998/04/16 09:14:57 achim
+ * Reserve drives (for raw service) implemented
+ * New error handling code enabled
+ * Get controller name from board_info() IOCTL
+ * Final round of PCI device driver patches by Martin Mares
+ *
+ * Revision 1.12 1998/03/03 09:32:37 achim
+ * Fibre channel controller support added
+ *
+ * Revision 1.11 1998/01/27 16:19:14 achim
+ * SA_SHIRQ added
+ * add_timer()/del_timer() instead of GDTH_TIMER
+ * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER
+ * New error handling included
*
* Revision 1.10 1997/10/31 12:29:57 achim
* Read heads/sectors from host drive
*
* Revision 1.9 1997/09/04 10:07:25 achim
- * IO-mapping with virt_to_bus(), readb(), writeb(), ...
+ * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
* register_reboot_notifier() to get a notify on shutdown used
*
* Revision 1.8 1997/04/02 12:14:30 achim
@@ -72,9 +94,49 @@
* Revision 1.1 1996/04/11 07:35:57 achim
* Initial revision
*
- *
- * $Id: gdth.c,v 1.4 1998/04/15 14:35:26 mj Exp $
************************************************************************/
+#ident "$Id: gdth.c,v 1.17 1998/12/17 15:58:11 achim Exp $"
+
+/* All GDT Disk Array Controllers are fully supported by this driver.
+ * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
+ * PCI Fibre Channel Disk Array Controllers. See gdth.h for a complete
+ * list of all controller types.
+ *
+ * If you have one or more GDT3000/3020 EISA controllers with
+ * controller BIOS disabled, you have to set the IRQ values with the
+ * command line option "gdth=irq1,irq2,...", where the irq1,irq2,... are
+ * the IRQ values for the EISA controllers.
+ *
+ * After the optional list of IRQ values, other possible
+ * command line options are:
+ * disable:Y disable driver
+ * disable:N enable driver
+ * reserve_mode:0 reserve no drives for the raw service
+ * reserve_mode:1 reserve all not init., removable drives
+ * reserve_mode:2 reserve all not init. drives
+ * reserve_list:h,b,t,l,h,b,t,l,... reserve particular drive(s) with
+ * h- controller no., b- channel no.,
+ * t- target ID, l- LUN
+ * reverse_scan:Y reverse scan order for PCI controllers
+ * reverse_scan:N scan PCI controllers like BIOS
+ * max_ids:x x - target ID count per channel (1..MAXID)
+ * rescan:Y rescan all channels/IDs
+ * rescan:N use all devices found until now
+ *
+ * The default value is: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
+ * max_ids:127,rescan:N".
+ * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
+ *
+ * When loading the gdth driver as a module, the same options are available.
+ * You can set the IRQs with "IRQ=...". However, the syntax to specify the
+ * options changes slightly. You must replace all ',' between options
+ * with ' ' and all ':' with '=' and you must use
+ * '1' in place of 'Y' and '0' in place of 'N'.
+ *
+ * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
+ * max_ids=127 rescan=0"
+ * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
+ */
#ifdef MODULE
#include <linux/module.h>
@@ -85,6 +147,7 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/string.h>
+#include <linux/ctype.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/sched.h>
@@ -101,7 +164,9 @@
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
+#if LINUX_VERSION_CODE >= 0x02015F
#include <asm/spinlock.h>
+#endif
#if LINUX_VERSION_CODE >= 0x010300
#include <linux/blk.h>
@@ -116,33 +181,34 @@
#if LINUX_VERSION_CODE >= 0x010346
static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-static void do_gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
#else
static void gdth_interrupt(int irq,struct pt_regs *regs);
#endif
static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
static int gdth_async_event(int hanum,int service);
+static void gdth_log_event(gdth_evt_data *dvr);
static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority);
static void gdth_next(int hanum);
static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
-static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b);
-static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
- gdth_evt_data *evt);
-static int gdth_read_event(int handle, gdth_evt_str *estr);
-static void gdth_readapp_event(unchar application, gdth_evt_str *estr);
+static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp);
+static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
+ ushort idx, gdth_evt_data *evt);
+static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr);
+static void gdth_readapp_event(gdth_ha_str *ha, unchar application,
+ gdth_evt_str *estr);
static void gdth_clear_events(void);
static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
-static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
- unchar b,ulong *flags);
+static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
static int gdth_search_eisa(ushort eisa_adr);
-static int gdth_search_isa(ulong bios_adr);
-static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr);
+static int gdth_search_isa(ulong32 bios_adr);
+static int gdth_search_pci(gdth_pci_str *pcistr);
+static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt);
static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha);
-static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha);
+static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha);
static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha);
static void gdth_enable_int(int hanum);
@@ -150,38 +216,28 @@ static int gdth_get_status(unchar *pIStatus,int irq);
static int gdth_test_busy(int hanum);
static int gdth_get_cmd_index(int hanum);
static void gdth_release_event(int hanum);
-static int gdth_wait(int hanum,int index,ulong time);
-static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
- ulong p2,ulong p3);
+static int gdth_wait(int hanum,int index,ulong32 time);
+static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
+ ulong32 p2,ulong32 p3);
static int gdth_search_drives(int hanum);
static void *gdth_mmap(ulong paddr, ulong size);
static void gdth_munmap(void *addr);
static const char *gdth_ctr_name(int hanum);
+
+static void gdth_flush(int hanum);
#if LINUX_VERSION_CODE >= 0x020100
static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
#else
+static int halt_called = FALSE;
void gdth_halt(void);
#endif
#ifdef DEBUG_GDTH
static unchar DebugState = DEBUG_GDTH;
extern int sys_syslog(int,char*,int);
-#define LOGEN sys_syslog(7,NULL,0);
-#define WAITSEC(a) mdelay((a)*1000)
-
-#ifdef SLOWMOTION_GDTH
-#define SLOWM WAITSEC(2)
-#undef INIT_RETRIES
-#undef INIT_TIMEOUT
-#undef POLL_TIMEOUT
-#define INIT_RETRIES 15
-#define INIT_TIMEOUT 150
-#define POLL_TIMEOUT 150
-#else
-#define SLOWM
-#endif
+#define LOGEN sys_syslog(7,NULL,0)
#ifdef __SERIAL__
#define MAX_SERBUF 160
@@ -245,14 +301,14 @@ static int ser_printk(const char *fmt, ...)
return i;
}
-#define TRACE(a) {if (DebugState==1) {ser_printk a; SLOWM}}
-#define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a; SLOWM}}
-#define TRACE3(a) {if (DebugState!=0) {ser_printk a; SLOWM}}
+#define TRACE(a) {if (DebugState==1) {ser_printk a;}}
+#define TRACE2(a) {if (DebugState==1 || DebugState==2) {ser_printk a;}}
+#define TRACE3(a) {if (DebugState!=0) {ser_printk a;}}
#else /* !__SERIAL__ */
-#define TRACE(a) {if (DebugState==1) {LOGEN;printk a; SLOWM}}
-#define TRACE2(a) {if (DebugState==1 || DebugState==2) {LOGEN;printk a; SLOWM}}
-#define TRACE3(a) {if (DebugState!=0) {LOGEN;printk a; SLOWM}}
+#define TRACE(a) {if (DebugState==1) {LOGEN;printk a;}}
+#define TRACE2(a) {if (DebugState==1 || DebugState==2) {LOGEN;printk a;}}
+#define TRACE3(a) {if (DebugState!=0) {LOGEN;printk a;}}
#endif
#else /* !DEBUG */
@@ -262,70 +318,77 @@ static int ser_printk(const char *fmt, ...)
#endif
#ifdef GDTH_STATISTICS
-static ulong max_rq=0, max_index=0, max_sg=0;
-static ulong act_ints=0, act_ios=0, act_stats=0, act_rq=0;
-#define GDTH_TIMER 31 /* see linux/timer.h ! */
+static ulong32 max_rq=0, max_index=0, max_sg=0;
+static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0;
+static struct timer_list gdth_timer;
#endif
#define PTR2USHORT(a) (ushort)(ulong)(a)
-#define JIFFYWAIT(a) {ulong gdtjf;gdtjf=jiffies+(a);while(gdtjf>jiffies);}
#define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b)
#define INDEX_OK(i,t) ((i)<sizeof(t)/sizeof((t)[0]))
#define NUMDATA(a) ( (gdth_num_str *)((a)->hostdata))
#define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext)
#define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext)
-#define DMADATA(a) (&((gdth_ext_str *)((a)->hostdata))->dmaext)
#if LINUX_VERSION_CODE < 0x010300
static void *gdth_mmap(ulong paddr, ulong size)
{
if (paddr >= high_memory)
- return NULL;
+ return NULL;
else
- return (void *)paddr;
+ return (void *)paddr;
}
static void gdth_munmap(void *addr)
{
}
-inline ulong virt_to_phys(volatile void *addr)
+inline ulong32 virt_to_phys(volatile void *addr)
{
- return (ulong)addr;
+ return (ulong32)addr;
}
-inline void *phys_to_virt(ulong addr)
+inline void *phys_to_virt(ulong32 addr)
{
return (void *)addr;
}
-#define virt_to_bus virt_to_phys
-#define bus_to_virt phys_to_virt
-#define readb(addr) (*(volatile unchar *)(addr))
-#define readw(addr) (*(volatile ushort *)(addr))
-#define readl(addr) (*(volatile ulong *)(addr))
-#define writeb(b,addr) (*(volatile unchar *)(addr) = (b))
-#define writew(b,addr) (*(volatile ushort *)(addr) = (b))
-#define writel(b,addr) (*(volatile ulong *)(addr) = (b))
-#define memset_io(a,b,c) memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+#define gdth_readb(addr) (*(volatile unchar *)(addr))
+#define gdth_readw(addr) (*(volatile ushort *)(addr))
+#define gdth_readl(addr) (*(volatile ulong32 *)(addr))
+#define gdth_writeb(b,addr) (*(volatile unchar *)(addr) = (b))
+#define gdth_writew(b,addr) (*(volatile ushort *)(addr) = (b))
+#define gdth_writel(b,addr) (*(volatile ulong32 *)(addr) = (b))
+#define memset_io(a,b,c) memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
+
+#define PCI_SLOT(devfn) ((devfn >> 3) & 0x1f)
#elif LINUX_VERSION_CODE < 0x020100
static int remapped = FALSE;
static void *gdth_mmap(ulong paddr, ulong size)
{
if ( paddr >= high_memory) {
- remapped = TRUE;
- return vremap(paddr, size);
+ remapped = TRUE;
+ return vremap(paddr, size);
} else {
- return (void *)paddr;
+ return (void *)paddr;
}
}
static void gdth_munmap(void *addr)
{
if (remapped)
- vfree(addr);
+ vfree(addr);
remapped = FALSE;
}
+#define gdth_readb(addr) readb((ulong)(addr))
+#define gdth_readw(addr) readw((ulong)(addr))
+#define gdth_readl(addr) (ulong32)readl((ulong)(addr))
+#define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
+#define gdth_writew(b,addr) writew((b),(ulong)(addr))
+#define gdth_writel(b,addr) writel((b),(ulong)(addr))
+
#else
static void *gdth_mmap(ulong paddr, ulong size)
{
@@ -335,6 +398,12 @@ static void gdth_munmap(void *addr)
{
return iounmap(addr);
}
+#define gdth_readb(addr) readb((ulong)(addr))
+#define gdth_readw(addr) readw((ulong)(addr))
+#define gdth_readl(addr) (ulong32)readl((ulong)(addr))
+#define gdth_writeb(b,addr) writeb((b),(ulong)(addr))
+#define gdth_writew(b,addr) writew((b),(ulong)(addr))
+#define gdth_writel(b,addr) writel((b),(ulong)(addr))
#endif
@@ -345,19 +414,14 @@ static unchar gdth_from_wait = FALSE; /* gdth_wait() */
static int wait_index,wait_hanum; /* gdth_wait() */
static int gdth_ctr_count = 0; /* controller count */
static int gdth_ctr_vcount = 0; /* virt. ctr. count */
+static int gdth_ctr_released = 0; /* gdth_release() */
static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */
static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS]; /* virt. ctr. table */
static unchar gdth_write_through = FALSE; /* write through */
-static char *gdth_ioctl_tab[4][MAXHA]; /* ioctl buffer */
static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */
static int elastidx;
static int eoldidx;
-static struct {
- Scsi_Cmnd *cmnd; /* pending request */
- ushort service; /* service */
-} gdth_cmd_tab[GDTH_MAXCMDS][MAXHA]; /* table of pend. requests */
-
#define DIN 1 /* IN data direction */
#define DOU 2 /* OUT data direction */
#define DNO DIN /* no data transfer */
@@ -381,17 +445,34 @@ static unchar gdth_direction_tab[0x100] = {
DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN
};
-/* LILO params: gdth=<IRQ>
- *
- * Where: <IRQ> is any of the valid IRQs for EISA controllers (10,11,12,14)
- * Sets the IRQ of the GDT3000/3020 EISA controller to this value,
- * if the IRQ can not automat. detect (controller BIOS disabled)
- * See gdth_init_eisa()
- *
- * You can use the command line gdth=0 to disable the driver
- */
-static unchar irqs[MAXHA] = {0xff};
-static unchar disable_gdth_scan = FALSE;
+/* __initfunc, __initdata macros */
+#if LINUX_VERSION_CODE >= 0x020126
+#include <linux/init.h>
+#else
+#define __initfunc(A) A
+#define __initdata
+#define __init
+#endif
+
+#if LINUX_VERSION_CODE >= 0x02015F
+#define GDTH_INIT_LOCK_HA(ha) spin_lock_init(&(ha)->smp_lock)
+#define GDTH_LOCK_HA(ha,flags) spin_lock_irqsave(&(ha)->smp_lock,flags)
+#define GDTH_UNLOCK_HA(ha,flags) spin_unlock_irqrestore(&(ha)->smp_lock,flags)
+
+#define GDTH_LOCK_SCSI_DONE(flags) spin_lock_irqsave(&io_request_lock,flags)
+#define GDTH_UNLOCK_SCSI_DONE(flags) spin_unlock_irqrestore(&io_request_lock,flags)
+#define GDTH_LOCK_SCSI_DOCMD() spin_lock_irq(&io_request_lock)
+#define GDTH_UNLOCK_SCSI_DOCMD() spin_unlock_irq(&io_request_lock)
+#else
+#define GDTH_INIT_LOCK_HA(ha) do {} while (0)
+#define GDTH_LOCK_HA(ha,flags) do {save_flags(flags); cli();} while (0)
+#define GDTH_UNLOCK_HA(ha,flags) do {restore_flags(flags);} while (0)
+
+#define GDTH_LOCK_SCSI_DONE(flags) do {} while (0)
+#define GDTH_UNLOCK_SCSI_DONE(flags) do {} while (0)
+#define GDTH_LOCK_SCSI_DOCMD() do {} while (0)
+#define GDTH_UNLOCK_SCSI_DOCMD() do {} while (0)
+#endif
/* /proc support */
#if LINUX_VERSION_CODE >= 0x010300
@@ -411,11 +492,63 @@ static struct notifier_block gdth_notifier = {
};
#endif
+
+/* LILO and modprobe/insmod parameters */
+/* IRQ list for GDT3000/3020 EISA controllers */
+static int irq[MAXHA] __initdata =
+{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+/* disable driver flag */
+static int disable __initdata = 0;
+/* reserve flag */
+static int reserve_mode __initdata = 1;
+/* reserve list */
+static int reserve_list[MAX_RES_ARGS] __initdata =
+{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
+/* scan order for PCI controllers */
+static int reverse_scan __initdata = 0;
+/* max. IDs per channel */
+static int max_ids = MAXID;
+/* rescan all IDs */
+static int rescan = 0;
+
+#ifdef MODULE
+#if LINUX_VERSION_CODE >= 0x02011A
+/* parameters for modprobe/insmod */
+MODULE_PARM(irq, "i");
+MODULE_PARM(disable, "i");
+MODULE_PARM(reserve_mode, "i");
+MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
+MODULE_PARM(reverse_scan, "i");
+MODULE_PARM(max_ids, "i");
+MODULE_PARM(rescan, "i");
+MODULE_AUTHOR("Achim Leubner");
+#endif
+#endif
+
+
+static void gdth_delay(int milliseconds)
+{
+ if (milliseconds == 0) {
+ udelay(1);
+ } else {
+#if LINUX_VERSION_CODE >= 0x020168
+ mdelay(milliseconds);
+#else
+ int i;
+ for (i = 0; i < milliseconds; ++i)
+ udelay(1000);
+#endif
+ }
+}
+
/* controller search and initialization functions */
-static int gdth_search_eisa(ushort eisa_adr)
+__initfunc (static int gdth_search_eisa(ushort eisa_adr))
{
- ulong id;
+ ulong32 id;
TRACE(("gdth_search_eisa() adr. %x\n",eisa_adr));
id = inl(eisa_adr+ID0REG);
@@ -431,99 +564,181 @@ static int gdth_search_eisa(ushort eisa_adr)
}
-static int gdth_search_isa(ulong bios_adr)
+__initfunc (static int gdth_search_isa(ulong32 bios_adr))
{
void *addr;
- ulong id;
+ ulong32 id;
- TRACE(("gdth_search_isa() bios adr. %lx\n",bios_adr));
- if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong))) != NULL) {
- id = readl(addr);
- gdth_munmap(addr);
- if (id == GDT2_ID) /* GDT2000 */
- return 1;
+ TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
+ if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
+ id = gdth_readl(addr);
+ gdth_munmap(addr);
+ if (id == GDT2_ID) /* GDT2000 */
+ return 1;
}
return 0;
}
-static int gdth_search_pci(ushort device_id,ushort index,gdth_pci_str *pcistr)
+__initfunc (static int gdth_search_pci(gdth_pci_str *pcistr))
{
+ ulong32 base0, base1, base2;
+ ushort device_id, cnt;
+#if LINUX_VERSION_CODE >= 0x2015C
+ struct pci_dev *pdev;
+#else
int error;
- ulong base0,base1,base2;
-
- TRACE(("gdth_search_pci() device_id %d, index %d\n",
- device_id,index));
-
- if (!pci_present())
- return 0;
-
- if (pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,index,
- &pcistr->bus,&pcistr->device_fn))
- return 0;
+ ushort idx;
+#endif
+
+ TRACE(("gdth_search_pci()\n"));
- /* GDT PCI controller found, now read resources from config space */
-#if LINUX_VERSION_CODE >= 0x20155
- {
- struct pci_dev *pdev = pci_find_slot(pcistr->bus, pcistr->device_fn);
- base0 = pdev->base_address[0];
- base1 = pdev->base_address[1];
- base2 = pdev->base_address[2];
- if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
- PCI_ROM_ADDRESS,
- (int *) &pcistr->bios))) {
- printk("GDT-PCI: error %d reading configuration space", error);
- return -1;
- }
- pcistr->irq = pdev->irq;
- }
-#else
+ cnt = 0;
+ for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDTMAXRP;
+ ++device_id) {
+ if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
+ device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
+ continue;
+#if LINUX_VERSION_CODE >= 0x2015C
+ pdev = NULL;
+ while ((pdev = pci_find_device(PCI_VENDOR_ID_VORTEX,device_id,pdev))
+ != NULL) {
+ if (cnt >= MAXHA)
+ return cnt;
+ /* GDT PCI controller found, resources are already in pdev */
+ pcistr[cnt].pdev = pdev;
+ pcistr[cnt].device_id = device_id;
+ pcistr[cnt].bus = pdev->bus->number;
+ pcistr[cnt].device_fn = pdev->devfn;
+ pcistr[cnt].irq = pdev->irq;
+ base0 = pdev->base_address[0];
+ base1 = pdev->base_address[1];
+ base2 = pdev->base_address[2];
+ if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
+ device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
+ if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_MEMORY)
+ continue;
+ pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+ } else { /* GDT6110, GDT6120, .. */
+ if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_MEMORY ||
+ (base2 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_MEMORY ||
+ (base1 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_IO)
+ continue;
+ pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
+ pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+ pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
+ }
+ TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
+ pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn),
+ pcistr[cnt].irq, pcistr[cnt].dpmem));
+ cnt++;
+ }
+#else
+ idx = 0;
+ while (!pcibios_find_device(PCI_VENDOR_ID_VORTEX,device_id,idx++,
+ &pcistr[cnt].bus,&pcistr[cnt].device_fn)) {
+ if (cnt >= MAXHA)
+ return cnt;
+ /* GDT PCI ctr. found, now read resources from config space */
#if LINUX_VERSION_CODE >= 0x010300
#define GDTH_BASEP (int *)
#else
#define GDTH_BASEP
#endif
- if ((error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
- PCI_BASE_ADDRESS_0,
- GDTH_BASEP&base0)) ||
- (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
- PCI_BASE_ADDRESS_1,
- GDTH_BASEP&base1)) ||
- (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
- PCI_BASE_ADDRESS_2,
- GDTH_BASEP&base2)) ||
- (error = pcibios_read_config_dword(pcistr->bus,pcistr->device_fn,
- PCI_ROM_ADDRESS,
- GDTH_BASEP&pcistr->bios)) ||
- (error = pcibios_read_config_byte(pcistr->bus,pcistr->device_fn,
- PCI_INTERRUPT_LINE,&pcistr->irq))) {
- printk("GDT-PCI: error %d reading configuration space", error);
- return -1;
- }
-#endif
-
- pcistr->device_id = device_id;
- if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000 or GDT6000B */
- device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
- if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY)
- return -1;
- pcistr->dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
- } else { /* GDT6110, GDT6120, .. */
- if ((base0 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
- (base2 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_MEMORY ||
- (base1 & PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO)
- return -1;
- pcistr->dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
- pcistr->io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
- pcistr->io = base1 & PCI_BASE_ADDRESS_IO_MASK;
- }
- return 1;
+ if ((error = pcibios_read_config_dword(pcistr[cnt].bus,
+ pcistr[cnt].device_fn,
+ PCI_BASE_ADDRESS_0,
+ GDTH_BASEP&base0)) ||
+ (error = pcibios_read_config_dword(pcistr[cnt].bus,
+ pcistr[cnt].device_fn,
+ PCI_BASE_ADDRESS_1,
+ GDTH_BASEP&base1)) ||
+ (error = pcibios_read_config_dword(pcistr[cnt].bus,
+ pcistr[cnt].device_fn,
+ PCI_BASE_ADDRESS_2,
+ GDTH_BASEP&base2)) ||
+ (error = pcibios_read_config_byte(pcistr[cnt].bus,
+ pcistr[cnt].device_fn,
+ PCI_INTERRUPT_LINE,
+ &pcistr[cnt].irq))) {
+ printk("GDT-PCI: error %d reading configuration space", error);
+ continue;
+ }
+ pcistr[cnt].device_id = device_id;
+ if (device_id <= PCI_DEVICE_ID_VORTEX_GDT6000B || /* GDT6000/B */
+ device_id >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) { /* MPR */
+ if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_MEMORY)
+ continue;
+ pcistr[cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+ } else { /* GDT6110, GDT6120, .. */
+ if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_MEMORY ||
+ (base2 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_MEMORY ||
+ (base1 & PCI_BASE_ADDRESS_SPACE) !=
+ PCI_BASE_ADDRESS_SPACE_IO)
+ continue;
+ pcistr[cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
+ pcistr[cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
+ pcistr[cnt].io = base1 & PCI_BASE_ADDRESS_IO_MASK;
+ }
+ TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%x\n",
+ pcistr[cnt].bus, PCI_SLOT(pcistr[cnt].device_fn),
+ pcistr[cnt].irq, pcistr[cnt].dpmem));
+ cnt++;
+ }
+#endif
+ }
+ return cnt;
+}
+
+
+__initfunc (static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt))
+{
+ gdth_pci_str temp;
+ int i, changed;
+
+ TRACE(("gdth_sort_pci() cnt %d\n",cnt));
+ if (cnt == 0)
+ return;
+
+ do {
+ changed = FALSE;
+ for (i = 0; i < cnt-1; ++i) {
+ if (!reverse_scan) {
+ if ((pcistr[i].bus > pcistr[i+1].bus) ||
+ (pcistr[i].bus == pcistr[i+1].bus &&
+ PCI_SLOT(pcistr[i].device_fn) >
+ PCI_SLOT(pcistr[i+1].device_fn))) {
+ temp = pcistr[i];
+ pcistr[i] = pcistr[i+1];
+ pcistr[i+1] = temp;
+ changed = TRUE;
+ }
+ } else {
+ if ((pcistr[i].bus < pcistr[i+1].bus) ||
+ (pcistr[i].bus == pcistr[i+1].bus &&
+ PCI_SLOT(pcistr[i].device_fn) <
+ PCI_SLOT(pcistr[i+1].device_fn))) {
+ temp = pcistr[i];
+ pcistr[i] = pcistr[i+1];
+ pcistr[i+1] = temp;
+ changed = TRUE;
+ }
+ }
+ }
+ } while (changed);
}
-static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
+__initfunc (static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha))
{
- ulong retries,id;
+ ulong32 retries,id;
unchar prot_ver,eisacf,i,irq_found;
TRACE(("gdth_init_eisa() adr. %x\n",eisa_adr));
@@ -535,14 +750,14 @@ static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
outb(0xff,eisa_adr+LDOORREG);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
+ gdth_delay(20);
while (inb(eisa_adr+EDOORREG) != 0xff) {
if (--retries == 0) {
printk("GDT-EISA: Initialization error (DEINIT failed)\n");
return 0;
}
- mdelay(1);
- TRACE2(("wait for DEINIT: retries=%ld\n",retries));
+ gdth_delay(1);
+ TRACE2(("wait for DEINIT: retries=%d\n",retries));
}
prot_ver = inb(eisa_adr+MAILBOXREG);
outb(0xff,eisa_adr+EDOORREG);
@@ -551,7 +766,7 @@ static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
return 0;
}
ha->bmic = eisa_adr;
- ha->brd_phys = (ulong)eisa_adr >> 12;
+ ha->brd_phys = (ulong32)eisa_adr >> 12;
outl(0,eisa_adr+MAILBOXREG);
outl(0,eisa_adr+MAILBOXREG+4);
@@ -565,76 +780,82 @@ static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha)
outl(1,eisa_adr+MAILBOXREG+8);
outb(0xfe,eisa_adr+LDOORREG);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
+ gdth_delay(20);
while (inb(eisa_adr+EDOORREG) != 0xfe) {
if (--retries == 0) {
printk("GDT-EISA: Initialization error (get IRQ failed)\n");
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
ha->irq = inb(eisa_adr+MAILBOXREG);
outb(0xff,eisa_adr+EDOORREG);
TRACE2(("GDT3000/3020: IRQ=%d\n",ha->irq));
- /* check the result */
- if (ha->irq == 0) {
- TRACE2(("Unknown IRQ, check IRQ table from cmd line !\n"));
- for (i=0,irq_found=FALSE; i<MAXHA && irqs[i]!=0xff; ++i) {
- if (irqs[i]!=0) {
- irq_found=TRUE;
- break;
- }
- }
- if (irq_found) {
- ha->irq = irqs[i];
- irqs[i] = 0;
- printk("GDT-EISA: Can not detect controller IRQ,\n");
- printk("Use IRQ setting from command line (IRQ = %d)\n",
- ha->irq);
- } else {
- printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
- printk("the controller BIOS or use command line parameters\n");
- return 0;
- }
- }
+ /* check the result */
+ if (ha->irq == 0) {
+ TRACE2(("Unknown IRQ, use IRQ table from cmd line !\n"));
+ for (i = 0, irq_found = FALSE;
+ i < MAXHA && irq[i] != 0xff; ++i) {
+ if (irq[i]==10 || irq[i]==11 || irq[i]==12 || irq[i]==14) {
+ irq_found = TRUE;
+ break;
+ }
+ }
+ if (irq_found) {
+ ha->irq = irq[i];
+ irq[i] = 0;
+ printk("GDT-EISA: Can not detect controller IRQ,\n");
+ printk("Use IRQ setting from command line (IRQ = %d)\n",
+ ha->irq);
+ } else {
+ printk("GDT-EISA: Initialization error (unknown IRQ), Enable\n");
+ printk("the controller BIOS or use command line parameters\n");
+ return 0;
+ }
+ }
} else {
eisacf = inb(eisa_adr+EISAREG) & 7;
if (eisacf > 4) /* level triggered */
eisacf -= 4;
ha->irq = gdth_irq_tab[eisacf];
ha->type = GDT_EISA;
- ha->stype= id;
+ ha->stype = id;
}
return 1;
}
-static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha)
+__initfunc (static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha))
{
register gdt2_dpram_str *dp2_ptr;
int i;
unchar irq_drq,prot_ver;
- ulong retries;
+ ulong32 retries;
- TRACE(("gdth_init_isa() bios adr. %lx\n",bios_adr));
+ TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr));
ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str));
if (ha->brd == NULL) {
- printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
- return 0;
+ printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
+ return 0;
}
dp2_ptr = (gdt2_dpram_str *)ha->brd;
- writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
+ gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */
/* reset interface area */
memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
+ if (gdth_readl(&dp2_ptr->u) != 0) {
+ printk("GDT-PCI: Initialization error (DPMEM write error)\n");
+ gdth_munmap(ha->brd);
+ return 0;
+ }
/* disable board interrupts, read DRQ and IRQ */
- writeb(0xff, &dp2_ptr->io.irqdel);
- writeb(0x00, &dp2_ptr->io.irqen);
- writeb(0x00, &dp2_ptr->u.ic.S_Status);
- writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
+ gdth_writeb(0xff, &dp2_ptr->io.irqdel);
+ gdth_writeb(0x00, &dp2_ptr->io.irqen);
+ gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status);
+ gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index);
- irq_drq = readb(&dp2_ptr->io.rq);
+ irq_drq = gdth_readb(&dp2_ptr->io.rq);
for (i=0; i<3; ++i) {
if ((irq_drq & 1)==0)
break;
@@ -642,7 +863,7 @@ static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha)
}
ha->drq = gdth_drq_tab[i];
- irq_drq = readb(&dp2_ptr->io.rq) >> 3;
+ irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3;
for (i=1; i<5; ++i) {
if ((irq_drq & 1)==0)
break;
@@ -651,25 +872,25 @@ static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha)
ha->irq = gdth_irq_tab[i];
/* deinitialize services */
- writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
- writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
- writeb(0, &dp2_ptr->io.event);
+ gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx);
+ gdth_writeb(0, &dp2_ptr->io.event);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
+ gdth_delay(20);
+ while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
if (--retries == 0) {
printk("GDT-ISA: Initialization error (DEINIT failed)\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]);
- writeb(0, &dp2_ptr->u.ic.Status);
- writeb(0xff, &dp2_ptr->io.irqdel);
+ prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0, &dp2_ptr->u.ic.Status);
+ gdth_writeb(0xff, &dp2_ptr->io.irqdel);
if (prot_ver != PROTOCOL_VERSION) {
printk("GDT-ISA: Illegal protocol version\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
@@ -679,83 +900,84 @@ static int gdth_init_isa(ulong bios_adr,gdth_ha_str *ha)
ha->brd_phys = bios_adr >> 4;
/* special request to controller BIOS */
- writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
- writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
- writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
- writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
- writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
- writeb(0, &dp2_ptr->io.event);
+ gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]);
+ gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]);
+ gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]);
+ gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]);
+ gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx);
+ gdth_writeb(0, &dp2_ptr->io.event);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
+ gdth_delay(20);
+ while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
if (--retries == 0) {
printk("GDT-ISA: Initialization error\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- writeb(0, &dp2_ptr->u.ic.Status);
- writeb(0xff, &dp2_ptr->io.irqdel);
+ gdth_writeb(0, &dp2_ptr->u.ic.Status);
+ gdth_writeb(0xff, &dp2_ptr->io.irqdel);
return 1;
}
-static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+__initfunc (static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha))
{
register gdt6_dpram_str *dp6_ptr;
register gdt6c_dpram_str *dp6c_ptr;
register gdt6m_dpram_str *dp6m_ptr;
- ulong retries;
+ ulong32 retries;
unchar prot_ver;
+ int i, found = FALSE;
TRACE(("gdth_init_pci()\n"));
ha->brd_phys = (pcistr->bus << 8) | (pcistr->device_fn & 0xf8);
- ha->stype = (ulong)pcistr->device_id;
+ ha->stype = (ulong32)pcistr->device_id;
ha->irq = pcistr->irq;
- if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000 or GDT6000B */
+ if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) { /* GDT6000/B */
TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
- ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
- if (ha->brd == NULL) {
- printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
- return 0;
- }
+ ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+ return 0;
+ }
dp6_ptr = (gdt6_dpram_str *)ha->brd;
/* reset interface area */
memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
- if (readl(&dp6_ptr->u) != 0) {
+ if (gdth_readl(&dp6_ptr->u) != 0) {
printk("GDT-PCI: Initialization error (DPMEM write error)\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
/* disable board interrupts, deinit services */
- writeb(0xff, &dp6_ptr->io.irqdel);
- writeb(0x00, &dp6_ptr->io.irqen);;
- writeb(0x00, &dp6_ptr->u.ic.S_Status);
- writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
-
- writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
- writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
- writeb(0, &dp6_ptr->io.event);
+ gdth_writeb(0xff, &dp6_ptr->io.irqdel);
+ gdth_writeb(0x00, &dp6_ptr->io.irqen);;
+ gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status);
+ gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
+
+ gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx);
+ gdth_writeb(0, &dp6_ptr->io.event);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
+ gdth_delay(20);
+ while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
if (--retries == 0) {
printk("GDT-PCI: Initialization error (DEINIT failed)\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]);
- writeb(0, &dp6_ptr->u.ic.S_Status);
- writeb(0xff, &dp6_ptr->io.irqdel);
+ prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
+ gdth_writeb(0xff, &dp6_ptr->io.irqdel);
if (prot_ver != PROTOCOL_VERSION) {
printk("GDT-PCI: Illegal protocol version\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
@@ -763,41 +985,41 @@ static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
ha->ic_all_size = sizeof(dp6_ptr->u);
/* special command to controller BIOS */
- writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
- writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
- writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
- writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
- writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
- writeb(0, &dp6_ptr->io.event);
+ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
+ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
+ gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
+ gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
+ gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
+ gdth_writeb(0, &dp6_ptr->io.event);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
+ gdth_delay(20);
+ while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
if (--retries == 0) {
printk("GDT-PCI: Initialization error\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
- }
- writeb(0, &dp6_ptr->u.ic.S_Status);
- writeb(0xff, &dp6_ptr->io.irqdel);
-
- } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, GDT6120, .. */
- ha->plx = (gdt6c_plx_regs *)pcistr->io;
- TRACE2(("init_pci_new() dpmem %lx io %lx irq %d\n",
- pcistr->dpmem,(ulong)ha->plx,ha->irq));
- ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
- if (ha->brd == NULL) {
- printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
- gdth_munmap(ha->brd);
- return 0;
- }
+ gdth_delay(1);
+ }
+ gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
+ gdth_writeb(0xff, &dp6_ptr->io.irqdel);
+
+ } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */
+ ha->plx = (gdt6c_plx_regs *)pcistr->io;
+ TRACE2(("init_pci_new() dpmem %lx irq %d\n",
+ pcistr->dpmem,ha->irq));
+ ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+ gdth_munmap(ha->brd);
+ return 0;
+ }
dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
/* reset interface area */
memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
- if (readl(&dp6c_ptr->u) != 0) {
+ if (gdth_readl(&dp6c_ptr->u) != 0) {
printk("GDT-PCI: Initialization error (DPMEM write error)\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
@@ -805,29 +1027,29 @@ static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
outb(0x00,PTR2USHORT(&ha->plx->control1));
outb(0xff,PTR2USHORT(&ha->plx->edoor_reg));
- writeb(0x00, &dp6c_ptr->u.ic.S_Status);
- writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
+ gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status);
+ gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index);
- writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
- writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
+ gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx);
outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
+ gdth_delay(20);
+ while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
if (--retries == 0) {
printk("GDT-PCI: Initialization error (DEINIT failed)\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]);
- writeb(0, &dp6c_ptr->u.ic.Status);
+ prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0, &dp6c_ptr->u.ic.Status);
if (prot_ver != PROTOCOL_VERSION) {
printk("GDT-PCI: Illegal protocol version\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
@@ -835,68 +1057,106 @@ static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
ha->ic_all_size = sizeof(dp6c_ptr->u);
/* special command to controller BIOS */
- writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
- writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
- writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
- writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
- writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
+ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
+ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
+ gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
+ gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
+ gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
outb(1,PTR2USHORT(&ha->plx->ldoor_reg));
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
+ gdth_delay(20);
+ while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
if (--retries == 0) {
printk("GDT-PCI: Initialization error\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- writeb(0, &dp6c_ptr->u.ic.S_Status);
+ gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
} else { /* MPR */
- TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
- ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
- if (ha->brd == NULL) {
- printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
- return 0;
- }
+ TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
+ ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+ return 0;
+ }
+ /* check and reset interface area */
dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
- /* reset interface area */
- memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
- if (readl(&dp6m_ptr->u) != 0) {
- printk("GDT-PCI: Initialization error (DPMEM write error)\n");
- gdth_munmap(ha->brd);
- return 0;
+ gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
+ if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) {
+ printk("GDT-PCI: Cannot access DPMEM at 0x%x (shadowed?)\n",
+ (int)pcistr->dpmem);
+ found = FALSE;
+ for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
+ gdth_munmap(ha->brd);
+ ha->brd = gdth_mmap(i, sizeof(ushort));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+ return 0;
+ }
+ if (gdth_readw(ha->brd) != 0xffff) {
+ TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
+ continue;
+ }
+ gdth_munmap(ha->brd);
+#if LINUX_VERSION_CODE >= 0x2015C
+ pci_write_config_dword(pcistr->pdev,
+ PCI_BASE_ADDRESS_0, i);
+#else
+ pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
+ PCI_BASE_ADDRESS_0, i);
+#endif
+ ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str));
+ if (ha->brd == NULL) {
+ printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
+ return 0;
+ }
+ dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+ gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
+ if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) {
+ printk("GDT-PCI: Use free address at 0x%x\n", i);
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ printk("GDT-PCI: No free address found!\n");
+ gdth_munmap(ha->brd);
+ return 0;
+ }
}
+ memset_io((char *)&dp6m_ptr->u,0,sizeof(dp6m_ptr->u));
/* disable board interrupts, deinit services */
- writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
- &dp6m_ptr->i960r.edoor_en_reg);
- writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
- writeb(0x00, &dp6m_ptr->u.ic.S_Status);
- writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
-
- writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
- writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
- writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+ gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4,
+ &dp6m_ptr->i960r.edoor_en_reg);
+ gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+ gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status);
+ gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index);
+
+ gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx);
+ gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
+ gdth_delay(20);
+ while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
if (--retries == 0) {
printk("GDT-PCI: Initialization error (DEINIT failed)\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]);
- writeb(0, &dp6m_ptr->u.ic.S_Status);
+ prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]);
+ gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
if (prot_ver != PROTOCOL_VERSION) {
printk("GDT-PCI: Illegal protocol version\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
@@ -904,23 +1164,23 @@ static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
ha->ic_all_size = sizeof(dp6m_ptr->u);
/* special command to controller BIOS */
- writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
- writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
- writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
- writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
- writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
- writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+ gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
+ gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
+ gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
+ gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
+ gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
+ gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
retries = INIT_RETRIES;
- JIFFYWAIT(2);
- while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
+ gdth_delay(20);
+ while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
if (--retries == 0) {
printk("GDT-PCI: Initialization error\n");
- gdth_munmap(ha->brd);
+ gdth_munmap(ha->brd);
return 0;
}
- mdelay(1);
+ gdth_delay(1);
}
- writeb(0, &dp6m_ptr->u.ic.S_Status);
+ gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
}
return 1;
@@ -929,7 +1189,7 @@ static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
/* controller protocol functions */
-static void gdth_enable_int(int hanum)
+__initfunc (static void gdth_enable_int(int hanum))
{
gdth_ha_str *ha;
ulong flags;
@@ -939,9 +1199,7 @@ static void gdth_enable_int(int hanum)
TRACE(("gdth_enable_int() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
-
- save_flags(flags);
- cli();
+ GDTH_LOCK_HA(ha, flags);
if (ha->type == GDT_EISA) {
outb(0xff, ha->bmic + EDOORREG);
@@ -949,24 +1207,24 @@ static void gdth_enable_int(int hanum)
outb(0x01, ha->bmic + EINTENABREG);
} else if (ha->type == GDT_ISA) {
dp2_ptr = (gdt2_dpram_str *)ha->brd;
- writeb(1, &dp2_ptr->io.irqdel);
- writeb(0, &dp2_ptr->u.ic.Cmd_Index);
- writeb(1, &dp2_ptr->io.irqen);
+ gdth_writeb(1, &dp2_ptr->io.irqdel);
+ gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);
+ gdth_writeb(1, &dp2_ptr->io.irqen);
} else if (ha->type == GDT_PCI) {
dp6_ptr = (gdt6_dpram_str *)ha->brd;
- writeb(1, &dp6_ptr->io.irqdel);
- writeb(0, &dp6_ptr->u.ic.Cmd_Index);
- writeb(1, &dp6_ptr->io.irqen);
+ gdth_writeb(1, &dp6_ptr->io.irqdel);
+ gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);
+ gdth_writeb(1, &dp6_ptr->io.irqen);
} else if (ha->type == GDT_PCINEW) {
outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
outb(0x03, PTR2USHORT(&ha->plx->control1));
} else if (ha->type == GDT_PCIMPR) {
dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
- writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
- writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
- &dp6m_ptr->i960r.edoor_en_reg);
+ gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+ gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4,
+ &dp6m_ptr->i960r.edoor_en_reg);
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
}
@@ -976,7 +1234,7 @@ static int gdth_get_status(unchar *pIStatus,int irq)
int i;
TRACE(("gdth_get_status() irq %d ctr_count %d\n",
- irq,gdth_ctr_count));
+ irq,gdth_ctr_count));
*pIStatus = 0;
for (i=0; i<gdth_ctr_count; ++i) {
@@ -986,13 +1244,16 @@ static int gdth_get_status(unchar *pIStatus,int irq)
if (ha->type == GDT_EISA)
*pIStatus = inb((ushort)ha->bmic + EDOORREG);
else if (ha->type == GDT_ISA)
- *pIStatus = readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+ *pIStatus =
+ gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Cmd_Index);
else if (ha->type == GDT_PCI)
- *pIStatus = readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
+ *pIStatus =
+ gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Cmd_Index);
else if (ha->type == GDT_PCINEW)
*pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg));
else if (ha->type == GDT_PCIMPR)
- *pIStatus = readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
+ *pIStatus =
+ gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.edoor_reg);
if (*pIStatus)
return i; /* board found */
@@ -1012,13 +1273,14 @@ static int gdth_test_busy(int hanum)
if (ha->type == GDT_EISA)
gdtsema0 = (int)inb(ha->bmic + SEMA0REG);
else if (ha->type == GDT_ISA)
- gdtsema0 = (int)readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+ gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
else if (ha->type == GDT_PCI)
- gdtsema0 = (int)readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+ gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
else if (ha->type == GDT_PCINEW)
gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg));
else if (ha->type == GDT_PCIMPR)
- gdtsema0 = (int)readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+ gdtsema0 =
+ (int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
return (gdtsema0 & 1);
}
@@ -1033,10 +1295,10 @@ static int gdth_get_cmd_index(int hanum)
ha = HADATA(gdth_ctr_tab[hanum]);
for (i=0; i<GDTH_MAXCMDS; ++i) {
- if (gdth_cmd_tab[i][hanum].cmnd == UNUSED_CMND) {
- gdth_cmd_tab[i][hanum].cmnd = ha->pccb->RequestBuffer;
- gdth_cmd_tab[i][hanum].service = ha->pccb->Service;
- ha->pccb->CommandIndex = (ulong)i+2;
+ if (ha->cmd_tab[i].cmnd == UNUSED_CMND) {
+ ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer;
+ ha->cmd_tab[i].service = ha->pccb->Service;
+ ha->pccb->CommandIndex = (ulong32)i+2;
return (i+2);
}
}
@@ -1051,17 +1313,17 @@ static void gdth_set_sema0(int hanum)
TRACE(("gdth_set_sema0() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
- if (ha->type == GDT_EISA)
+ if (ha->type == GDT_EISA) {
outb(1, ha->bmic + SEMA0REG);
- else if (ha->type == GDT_ISA)
- writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
- else if (ha->type == GDT_PCI)
- writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
- else if (ha->type == GDT_PCINEW)
+ } else if (ha->type == GDT_ISA) {
+ gdth_writeb(1, &((gdt2_dpram_str *)ha->brd)->u.ic.Sema0);
+ } else if (ha->type == GDT_PCI) {
+ gdth_writeb(1, &((gdt6_dpram_str *)ha->brd)->u.ic.Sema0);
+ } else if (ha->type == GDT_PCINEW) {
outb(1, PTR2USHORT(&ha->plx->sema0_reg));
- else if (ha->type == GDT_PCIMPR)
- writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
-
+ } else if (ha->type == GDT_PCIMPR) {
+ gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg);
+ }
}
@@ -1096,31 +1358,31 @@ static void gdth_copy_command(int hanum)
/* set offset and service, copy command to DPMEM */
if (ha->type == GDT_ISA) {
dp2_ptr = (gdt2_dpram_str *)ha->brd;
- writew(dp_offset + DPMEM_COMMAND_OFFSET,
- &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
- writew((ushort)cmd_ptr->Service,
- &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
- memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
+ gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
+ &dp2_ptr->u.ic.comm_queue[cmd_no].offset);
+ gdth_writew((ushort)cmd_ptr->Service,
+ &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id);
+ memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
} else if (ha->type == GDT_PCI) {
dp6_ptr = (gdt6_dpram_str *)ha->brd;
- writew(dp_offset + DPMEM_COMMAND_OFFSET,
- &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
- writew((ushort)cmd_ptr->Service,
- &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
+ gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
+ &dp6_ptr->u.ic.comm_queue[cmd_no].offset);
+ gdth_writew((ushort)cmd_ptr->Service,
+ &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id);
memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
} else if (ha->type == GDT_PCINEW) {
dp6c_ptr = (gdt6c_dpram_str *)ha->brd;
- writew(dp_offset + DPMEM_COMMAND_OFFSET,
- &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
- writew((ushort)cmd_ptr->Service,
- &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
- memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
+ gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
+ &dp6c_ptr->u.ic.comm_queue[cmd_no].offset);
+ gdth_writew((ushort)cmd_ptr->Service,
+ &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id);
+ memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
} else if (ha->type == GDT_PCIMPR) {
dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
- writew(dp_offset + DPMEM_COMMAND_OFFSET,
- &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
- writew((ushort)cmd_ptr->Service,
- &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
+ gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET,
+ &dp6m_ptr->u.ic.comm_queue[cmd_no].offset);
+ gdth_writew((ushort)cmd_ptr->Service,
+ &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id);
memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count);
}
}
@@ -1130,21 +1392,23 @@ static void gdth_release_event(int hanum)
{
register gdth_ha_str *ha;
+ TRACE(("gdth_release_event() hanum %d\n",hanum));
+ ha = HADATA(gdth_ctr_tab[hanum]);
+
#ifdef GDTH_STATISTICS
- ulong i,j;
- for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
- if (gdth_cmd_tab[j][hanum].cmnd != UNUSED_CMND)
- ++i;
- }
- if (max_index < i) {
- max_index = i;
- TRACE3(("GDT: max_index = %d\n",(ushort)i));
+ {
+ ulong32 i,j;
+ for (i=0,j=0; j<GDTH_MAXCMDS; ++j) {
+ if (ha->cmd_tab[j].cmnd != UNUSED_CMND)
+ ++i;
+ }
+ if (max_index < i) {
+ max_index = i;
+ TRACE3(("GDT: max_index = %d\n",(ushort)i));
+ }
}
#endif
- TRACE(("gdth_release_event() hanum %d\n",hanum));
- ha = HADATA(gdth_ctr_tab[hanum]);
-
if (ha->pccb->OpCode == GDT_INIT)
ha->pccb->Service |= 0x80;
@@ -1152,23 +1416,24 @@ static void gdth_release_event(int hanum)
outb(ha->pccb->Service, ha->bmic + LDOORREG);
if (ha->pccb->OpCode == GDT_INIT) /* store DMA buffer */
outl((ulong)ha->pccb, ha->bmic + MAILBOXREG);
- } else if (ha->type == GDT_ISA)
- writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
- else if (ha->type == GDT_PCI)
- writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
- else if (ha->type == GDT_PCINEW)
+ } else if (ha->type == GDT_ISA) {
+ gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
+ } else if (ha->type == GDT_PCI) {
+ gdth_writeb(0, &((gdt6_dpram_str *)ha->brd)->io.event);
+ } else if (ha->type == GDT_PCINEW) {
outb(1, PTR2USHORT(&ha->plx->ldoor_reg));
- else if (ha->type == GDT_PCIMPR)
- writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
+ } else if (ha->type == GDT_PCIMPR) {
+ gdth_writeb(1, &((gdt6m_dpram_str *)ha->brd)->i960r.ldoor_reg);
+ }
}
-static int gdth_wait(int hanum,int index,ulong time)
+static int gdth_wait(int hanum,int index,ulong32 time)
{
gdth_ha_str *ha;
int answer_found = FALSE;
- TRACE(("gdth_wait() hanum %d index %d time %ld\n",hanum,index,time));
+ TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time));
ha = HADATA(gdth_ctr_tab[hanum]);
if (index == 0)
@@ -1177,7 +1442,7 @@ static int gdth_wait(int hanum,int index,ulong time)
gdth_from_wait = TRUE;
do {
#if LINUX_VERSION_CODE >= 0x010346
- gdth_interrupt((int)ha->irq,NULL,NULL);
+ gdth_interrupt((int)ha->irq,ha,NULL);
#else
gdth_interrupt((int)ha->irq,NULL);
#endif
@@ -1185,19 +1450,19 @@ static int gdth_wait(int hanum,int index,ulong time)
answer_found = TRUE;
break;
}
- mdelay(1);
+ gdth_delay(1);
} while (--time);
gdth_from_wait = FALSE;
while (gdth_test_busy(hanum))
- udelay(1);
+ gdth_delay(0);
return (answer_found);
}
-static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
- ulong p2,ulong p3)
+static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
+ ulong32 p2,ulong32 p3)
{
register gdth_ha_str *ha;
register gdth_cmd_str *cmd_ptr;
@@ -1234,21 +1499,21 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
cmd_ptr->u.raw.direction = p1;
cmd_ptr->u.raw.bus = (unchar)p2;
cmd_ptr->u.raw.target = (unchar)p3;
- cmd_ptr->u.raw.lun = 0;
+ cmd_ptr->u.raw.lun = (unchar)(p3 >> 8);
}
ha->cmd_len = sizeof(gdth_cmd_str);
ha->cmd_offs_dpmem = 0;
ha->cmd_cnt = 0;
gdth_copy_command(hanum);
gdth_release_event(hanum);
- JIFFYWAIT(2);
+ gdth_delay(20);
if (!gdth_wait(hanum,index,INIT_TIMEOUT)) {
printk("GDT: Initialization error (timeout service %d)\n",service);
return 0;
}
if (ha->status != S_BSY || --retries == 0)
break;
- mdelay(1);
+ gdth_delay(1);
}
return (ha->status != S_OK ? 0:1);
@@ -1257,14 +1522,14 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong p1,
/* search for devices */
-static int gdth_search_drives(int hanum)
+__initfunc (static int gdth_search_drives(int hanum))
{
register gdth_ha_str *ha;
- ushort cdev_cnt,i;
- unchar b,t,pos_found;
- ulong drv_cyls, drv_hds, drv_secs;
- ulong bus_no;
+ ushort cdev_cnt, i;
+ ulong32 drv_cyls, drv_hds, drv_secs;
+ ulong32 bus_no;
gdth_getch_str *chn;
+ gdth_iochan_str *ioc;
TRACE(("gdth_search_drives() hanum %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -1292,45 +1557,76 @@ static int gdth_search_drives(int hanum)
/* initialize cache service after mountall */
if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
- printk("GDT: Initialization error cache service (code %d)\n",
- ha->status);
- return 0;
+ printk("GDT: Initialization error cache service (code %d)\n",
+ ha->status);
+ return 0;
}
TRACE2(("gdth_search_drives() CACHES. init. after mountall\n"));
cdev_cnt = (ushort)ha->info;
- /* detect number of SCSI buses */
- chn = (gdth_getch_str *)DMADATA(gdth_ctr_tab[hanum]);
- for (bus_no=0; bus_no<MAXBUS; ++bus_no) {
- chn->channel_no = bus_no;
- if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
- SCSI_CHAN_CNT | L_CTRL_PATTERN,
- IO_CHANNEL | INVALID_CHANNEL,
- sizeof(gdth_getch_str))) {
- if (bus_no == 0) {
- printk("GDT: Error detecting SCSI channel count (0x%x)\n",
- ha->status);
- return 0;
- }
- break;
- }
- if (chn->siop_id < MAXID)
- ha->id[bus_no][chn->siop_id].type = SIOP_DTYP;
- }
- ha->bus_cnt = (unchar)bus_no;
- TRACE2(("gdth_search_drives() %d SCSI channels\n",ha->bus_cnt));
+ /* detect number of buses - try new IOCTL */
+ ioc = (gdth_iochan_str *)ha->pscratch;
+ ioc->version = 0xffffffff;
+ ioc->list_entries = MAXBUS;
+ ioc->first_chan = 0;
+ ioc->last_chan = MAXBUS-1;
+ ioc->list_offset = GDTOFFSOF(gdth_iochan_str, list[0]);
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,GET_IOCHAN_DESC,
+ INVALID_CHANNEL,sizeof(gdth_iochan_str))) {
+ TRACE2(("GET_IOCHAN_DESC supported!\n"));
+ ha->bus_cnt = ioc->chan_count;
+ for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) {
+ if (ioc->list[bus_no].proc_id < MAXID)
+ ha->bus_id[bus_no] = ioc->list[bus_no].proc_id;
+ else
+ ha->bus_id[bus_no] = 0xff;
+ }
+ } else {
+ /* old method */
+ chn = (gdth_getch_str *)ha->pscratch;
+ for (bus_no = 0; bus_no < MAXBUS; ++bus_no) {
+ chn->channel_no = bus_no;
+ if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+ SCSI_CHAN_CNT | L_CTRL_PATTERN,
+ IO_CHANNEL | INVALID_CHANNEL,
+ sizeof(gdth_getch_str))) {
+ if (bus_no == 0) {
+ printk("GDT: Error detecting channel count (0x%x)\n",
+ ha->status);
+ return 0;
+ }
+ break;
+ }
+ if (chn->siop_id < MAXID)
+ ha->bus_id[bus_no] = chn->siop_id;
+ else
+ ha->bus_id[bus_no] = 0xff;
+ }
+ ha->bus_cnt = (unchar)bus_no;
+ }
+ TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt));
/* read cache configuration */
if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
- INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
- printk("GDT: Initialization error cache service (code %d)\n",
- ha->status);
- return 0;
+ INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
+ printk("GDT: Initialization error cache service (code %d)\n",
+ ha->status);
+ return 0;
+ }
+ ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
+ TRACE2(("gdth_search_drives() cinfo: vs %x sta %d str %d dw %d b %d\n",
+ ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
+ ha->cpar.write_back,ha->cpar.block_size));
+
+ /* read board info, fill ctr_name[] */
+ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO,
+ INVALID_CHANNEL,sizeof(gdth_binfo_str))) {
+ TRACE2(("BOARD_INFO supported!\n"));
+ strcpy(ha->ctr_name, ((gdth_binfo_str *)ha->pscratch)->type_string);
+ } else {
+ strcpy(ha->ctr_name, gdth_ctr_name(hanum));
}
- ha->cpar = ((gdth_cinfo_str *)DMADATA(gdth_ctr_tab[hanum]))->cpar;
- TRACE2(("gdth_search_drives() cinfo: vs %lx sta %d str %d dw %d b %d\n",
- ha->cpar.version,ha->cpar.state,ha->cpar.strategy,
- ha->cpar.write_back,ha->cpar.block_size));
+ TRACE2(("Controller name: %s\n",ha->ctr_name));
/* initialize raw service */
if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
@@ -1345,10 +1641,9 @@ static int gdth_search_drives(int hanum)
if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER,
0,0)) {
TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n"));
- if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0))
- {
- TRACE2(("gdth_search_dr(): get feat RAWSERVICE %ld\n",
- ha->info));
+ if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
+ TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
+ ha->info));
ha->raw_feat = (ushort)ha->info;
}
}
@@ -1358,20 +1653,31 @@ static int gdth_search_drives(int hanum)
SCATTER_GATHER,0)) {
TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n"));
if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
- TRACE2(("gdth_search_dr(): get feat CACHESERV. %ld\n",
- ha->info));
+ TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
+ ha->info));
ha->cache_feat = (ushort)ha->info;
}
}
- /* scanning for raw devices */
- for (b=0; b<ha->bus_cnt; ++b) {
- for (t=0; t<MAXID; ++t) {
- TRACE(("gdth_search_drives() rawd. bus %d id %d\n",b,t));
- if (ha->id[b][t].type != SIOP_DTYP &&
- gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INFO,0,b,t)) {
- ha->id[b][t].type = RAW_DTYP;
- }
+ /* reserve drives for raw service */
+ if (reserve_mode != 0) {
+ gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL,
+ reserve_mode == 1 ? 1 : 3, 0, 0);
+ TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n",
+ ha->status));
+ }
+ for (i = 0; i < MAX_RES_ARGS; i += 4) {
+ if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt &&
+ reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) {
+ TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n",
+ reserve_list[i], reserve_list[i+1],
+ reserve_list[i+2], reserve_list[i+3]));
+ if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
+ reserve_list[i+1], reserve_list[i+2] |
+ (reserve_list[i+3] << 8))) {
+ printk("GDT: Error raw service (RESERVE, code %d)\n",
+ ha->status);
+ }
}
}
@@ -1379,63 +1685,49 @@ static int gdth_search_drives(int hanum)
for (i=0; i<cdev_cnt && i<MAX_HDRIVES; ++i) {
TRACE(("gdth_search_drives() cachedev. %d\n",i));
if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,i,0,0)) {
- /* dynamic relation between host drive number and Bus/ID */
- /* search free position */
- pos_found = FALSE;
- for (b=0,t=0; b<ha->bus_cnt; ++b) {
- for (t=0; t<MAXID; ++t) {
- if (ha->id[b][t].type == EMPTY_DTYP) {
- pos_found = TRUE;
- break;
- }
- }
- if (pos_found)
- break;
- }
- TRACE(("gdth_search_dr() drive %d free pos at bus/id %d/%d\n",
- i,b,t));
+ /* static relation between host drive number and Bus/ID */
+ TRACE(("gdth_search_dr() drive %d mapped to bus/id %d/%d\n",
+ i,ha->bus_cnt,i));
- ha->id[b][t].type = CACHE_DTYP;
- ha->id[b][t].devtype = 0;
- ha->id[b][t].size = ha->info;
- ha->id[b][t].hostdrive = i;
+ ha->hdr[i].present = TRUE;
+ ha->hdr[i].size = ha->info;
/* evaluate mapping (sectors per head, heads per cylinder) */
- ha->id[b][t].size &= ~SECS32;
- if (ha->info2 == 0) {
- drv_cyls = ha->id[b][t].size /HEADS/SECS;
- if (drv_cyls <= MAXCYLS) {
- drv_hds = HEADS;
- drv_secs= SECS;
- } else { /* too high for 64*32 */
- drv_cyls = ha->id[b][t].size /MEDHEADS/MEDSECS;
- if (drv_cyls <= MAXCYLS) {
- drv_hds = MEDHEADS;
- drv_secs= MEDSECS;
- } else { /* too high for 127*63 */
- drv_cyls = ha->id[b][t].size /BIGHEADS/BIGSECS;
- drv_hds = BIGHEADS;
- drv_secs= BIGSECS;
- }
- }
+ ha->hdr[i].size &= ~SECS32;
+ if (ha->info2 == 0) {
+ drv_cyls = ha->hdr[i].size /HEADS/SECS;
+ if (drv_cyls <= MAXCYLS) {
+ drv_hds = HEADS;
+ drv_secs= SECS;
+ } else { /* too high for 64*32 */
+ drv_cyls = ha->hdr[i].size /MEDHEADS/MEDSECS;
+ if (drv_cyls <= MAXCYLS) {
+ drv_hds = MEDHEADS;
+ drv_secs= MEDSECS;
+ } else { /* too high for 127*63 */
+ drv_cyls = ha->hdr[i].size /BIGHEADS/BIGSECS;
+ drv_hds = BIGHEADS;
+ drv_secs= BIGSECS;
+ }
+ }
} else {
- drv_hds = ha->info2 & 0xff;
- drv_secs = (ha->info2 >> 8) & 0xff;
- drv_cyls = ha->id[b][t].size /drv_hds/drv_secs;
- }
- ha->id[b][t].heads = (unchar)drv_hds;
- ha->id[b][t].secs = (unchar)drv_secs;
+ drv_hds = ha->info2 & 0xff;
+ drv_secs = (ha->info2 >> 8) & 0xff;
+ drv_cyls = ha->hdr[i].size /drv_hds/drv_secs;
+ }
+ ha->hdr[i].heads = (unchar)drv_hds;
+ ha->hdr[i].secs = (unchar)drv_secs;
/* round size */
- ha->id[b][t].size = drv_cyls * drv_hds * drv_secs;
- TRACE2(("gdth_search_dr() cdr. %d size %ld hds %ld scs %ld\n",
- i,ha->id[b][t].size,drv_hds,drv_secs));
+ ha->hdr[i].size = drv_cyls * drv_hds * drv_secs;
+ TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
+ i,ha->hdr[i].size,drv_hds,drv_secs));
/* get informations about device */
if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,i,
0,0)) {
- TRACE(("gdth_search_dr() cache drive %d devtype %ld\n",
+ TRACE(("gdth_search_dr() cache drive %d devtype %d\n",
i,ha->info));
- ha->id[b][t].devtype = (ushort)ha->info;
+ ha->hdr[i].devtype = (ushort)ha->info;
}
}
}
@@ -1456,12 +1748,11 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
unchar b, t;
TRACE(("gdth_putq() priority %d\n",priority));
- save_flags(flags);
- cli();
-
ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
+
scp->SCp.this_residual = (int)priority;
- gdth_update_timeout(scp, scp->timeout * 6);
+ gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
#if LINUX_VERSION_CODE >= 0x020000
b = scp->channel;
#else
@@ -1469,9 +1760,12 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
#endif
t = scp->target;
#if LINUX_VERSION_CODE >= 0x010300
- if (priority >= DEFAULT_PRI && ha->id[b][t].lock) {
- TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
- scp->SCp.buffers_residual = gdth_update_timeout(scp, 0);
+ if (priority >= DEFAULT_PRI) {
+ if ((b < ha->bus_cnt && ha->raw[b].lock) ||
+ (b == ha->bus_cnt && ha->hdr[t].lock)) {
+ TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
+ scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+ }
}
#endif
@@ -1489,7 +1783,7 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
pscp->SCp.ptr = (char *)scp;
scp->SCp.ptr = (char *)nscp;
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
#ifdef GDTH_STATISTICS
flags = 0;
@@ -1507,18 +1801,18 @@ static void gdth_next(int hanum)
register gdth_ha_str *ha;
register Scsi_Cmnd *pscp;
register Scsi_Cmnd *nscp;
- unchar b, t, next_cmd, firsttime;
- ushort hdrive;
+ unchar b, t, firsttime;
+ unchar this_cmd, next_cmd;
ulong flags;
int cmd_index;
TRACE(("gdth_next() hanum %d\n",hanum));
- save_flags(flags);
- cli();
-
ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
+
ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
- next_cmd = firsttime = TRUE;
+ this_cmd = firsttime = TRUE;
+ next_cmd = gdth_polling ? FALSE:TRUE;
cmd_index = 0;
for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
@@ -1530,105 +1824,173 @@ static void gdth_next(int hanum)
b = NUMDATA(nscp->host)->busnum;
#endif
t = nscp->target;
- if (nscp->SCp.this_residual < DEFAULT_PRI || !ha->id[b][t].lock) {
-
- if (firsttime) {
- if (gdth_test_busy(hanum)) { /* controller busy ? */
- TRACE(("gdth_next() controller %d busy !\n",hanum));
- if (!gdth_polling) {
- restore_flags(flags);
- return;
+ if (nscp->SCp.this_residual >= DEFAULT_PRI) {
+ if ((b < ha->bus_cnt && ha->raw[b].lock) ||
+ (b == ha->bus_cnt && ha->hdr[t].lock))
+ continue;
+ }
+
+ if (firsttime) {
+ if (gdth_test_busy(hanum)) { /* controller busy ? */
+ TRACE(("gdth_next() controller %d busy !\n",hanum));
+ if (!gdth_polling) {
+ GDTH_UNLOCK_HA(ha, flags);
+ return;
+ }
+ while (gdth_test_busy(hanum))
+ gdth_delay(1);
+ }
+ firsttime = FALSE;
+ }
+
+ if (nscp->SCp.phase == -1) {
+ nscp->SCp.phase = SCSIRAWSERVICE; /* default: raw svc. */
+ if (nscp->cmnd[0] == TEST_UNIT_READY) {
+ TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n",
+ nscp->channel, nscp->target, nscp->lun));
+ /* TEST_UNIT_READY -> set scan mode */
+ if ((ha->scan_mode & 0x0f) == 0) {
+ if (nscp->channel == 0 && nscp->target == 0 &&
+ nscp->lun == 0) {
+ ha->scan_mode |= 1;
+ TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
+ }
+ } else if ((ha->scan_mode & 0x0f) == 1) {
+ if (nscp->channel == 0 &&
+ ((nscp->target == 0 && nscp->lun == 1) ||
+ (nscp->target == 1 && nscp->lun == 0))) {
+ nscp->SCp.Status = GDT_SCAN_START;
+ nscp->SCp.phase |= ((ha->scan_mode & 0x10 ? 1:0) << 8);
+ ha->scan_mode = 0x12;
+ TRACE2(("Scan mode: 0x%x (SCAN_START)\n",
+ ha->scan_mode));
+ } else {
+ ha->scan_mode &= 0x10;
+ TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
+ }
+ } else if (ha->scan_mode == 0x12) {
+ if (b == ha->bus_cnt) {
+ nscp->SCp.Status = GDT_SCAN_END;
+ ha->scan_mode &= 0x10;
+ TRACE2(("Scan mode: 0x%x (SCAN_END)\n",
+ ha->scan_mode));
}
- while (gdth_test_busy(hanum))
- mdelay(1);
}
- firsttime = FALSE;
}
+ }
+
+ if (nscp->SCp.Status != -1) {
+ if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) {
+ cmd_index=gdth_fill_raw_cmd(hanum,nscp,b);
+ next_cmd = FALSE;
+ }
+ } else
#if LINUX_VERSION_CODE >= 0x010300
- if (nscp->done == gdth_scsi_done) {
- if (!(cmd_index=gdth_special_cmd(hanum,nscp,b)))
- next_cmd = FALSE;
- } else
-#endif
- if (ha->id[b][t].type != CACHE_DTYP) {
- if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b)))
- next_cmd = FALSE;
- } else {
- hdrive = ha->id[b][t].hostdrive;
- switch (nscp->cmnd[0]) {
- case TEST_UNIT_READY:
- case INQUIRY:
- case REQUEST_SENSE:
- case READ_CAPACITY:
- case VERIFY:
- case START_STOP:
- case MODE_SENSE:
- TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
- nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
- nscp->cmnd[4],nscp->cmnd[5]));
- gdth_internal_cache_cmd(hanum,nscp,b,&flags);
- break;
+ if (nscp->done == gdth_scsi_done) {
+ if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
+ this_cmd = FALSE;
+ next_cmd = FALSE;
+ } else
+#endif
+ if (b < ha->bus_cnt) {
+ if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,b))) {
+ this_cmd = FALSE;
+ }
+ } else if (!ha->hdr[nscp->target].present || nscp->lun != 0) {
+ TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
+ nscp->cmnd[0], b, nscp->target, nscp->lun));
+ nscp->result = DID_BAD_TARGET << 16;
+ GDTH_UNLOCK_HA(ha,flags);
+ /* io_request_lock already active ! */
+ nscp->scsi_done(nscp);
+ GDTH_LOCK_HA(ha,flags);
+ } else {
+ switch (nscp->cmnd[0]) {
+ case TEST_UNIT_READY:
+ case INQUIRY:
+ case REQUEST_SENSE:
+ case READ_CAPACITY:
+ case VERIFY:
+ case START_STOP:
+ case MODE_SENSE:
+ TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
+ nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
+ nscp->cmnd[4],nscp->cmnd[5]));
+ if (gdth_internal_cache_cmd(hanum,nscp)) {
+ GDTH_UNLOCK_HA(ha,flags);
+ /* io_request_lock already active ! */
+ nscp->scsi_done(nscp);
+ GDTH_LOCK_HA(ha,flags);
+ }
+ break;
- case ALLOW_MEDIUM_REMOVAL:
- TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
- nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
- nscp->cmnd[4],nscp->cmnd[5]));
- if ( (nscp->cmnd[4]&1) && !(ha->id[b][t].devtype&1) ) {
- TRACE2(("Prevent r. nonremov. drive->do nothing\n"));
- nscp->result = DID_OK << 16;
- restore_flags( flags );
+ case ALLOW_MEDIUM_REMOVAL:
+ TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
+ nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
+ nscp->cmnd[4],nscp->cmnd[5]));
+ if ( (nscp->cmnd[4]&1) && !(ha->hdr[t].devtype&1) ) {
+ TRACE(("Prevent r. nonremov. drive->do nothing\n"));
+ nscp->result = DID_OK << 16;
+ if (!nscp->SCp.have_data_in)
+ nscp->SCp.have_data_in++;
+ else {
+ GDTH_UNLOCK_HA(ha,flags);
+ /* io_request_lock already active ! */
nscp->scsi_done(nscp);
- save_flags( flags );
- cli();
- } else {
- nscp->cmnd[3] = (ha->id[b][t].devtype&1) ? 1:0;
- TRACE2(("Prevent/allow r. %d rem. drive %d\n",
- nscp->cmnd[4],nscp->cmnd[3]));
- if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
- next_cmd = FALSE;
+ GDTH_LOCK_HA(ha,flags);
}
- break;
-
- case READ_6:
- case WRITE_6:
- case READ_10:
- case WRITE_10:
- if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,hdrive)))
- next_cmd = FALSE;
- break;
+ } else {
+ nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
+ TRACE(("Prevent/allow r. %d rem. drive %d\n",
+ nscp->cmnd[4],nscp->cmnd[3]));
+ if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+ this_cmd = FALSE;
+ }
+ break;
+
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
+ this_cmd = FALSE;
+ break;
- default:
- TRACE2(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
+ default:
+ TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
nscp->cmnd[4],nscp->cmnd[5]));
- printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
+ printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
nscp->cmnd[0]);
- nscp->result = DID_ABORT << 16;
- restore_flags( flags );
- nscp->scsi_done( nscp );
- save_flags( flags );
- cli();
- break;
+ nscp->result = DID_ABORT << 16;
+ if (!nscp->SCp.have_data_in)
+ nscp->SCp.have_data_in++;
+ else {
+ GDTH_UNLOCK_HA(ha,flags);
+ /* io_request_lock already active ! */
+ nscp->scsi_done(nscp);
+ GDTH_LOCK_HA(ha,flags);
}
- }
-
- if (!next_cmd)
- break;
- if (nscp == ha->req_first)
- ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
- else
- pscp->SCp.ptr = nscp->SCp.ptr;
- if (gdth_polling)
break;
+ }
}
+
+ if (!this_cmd)
+ break;
+ if (nscp == ha->req_first)
+ ha->req_first = pscp = (Scsi_Cmnd *)nscp->SCp.ptr;
+ else
+ pscp->SCp.ptr = nscp->SCp.ptr;
+ if (!next_cmd)
+ break;
}
if (ha->cmd_cnt > 0) {
gdth_release_event(hanum);
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
if (gdth_polling && ha->cmd_cnt > 0) {
if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
@@ -1664,11 +2026,9 @@ static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count)
}
}
-static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
- unchar b,ulong *flags)
+static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp)
{
register gdth_ha_str *ha;
- ushort hdrive;
unchar t;
gdth_inq_data inq;
gdth_rdcap_data rdc;
@@ -1677,77 +2037,73 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp,
ha = HADATA(gdth_ctr_tab[hanum]);
t = scp->target;
- hdrive = ha->id[b][t].hostdrive;
TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
- scp->cmnd[0],hdrive));
-
- if (scp->lun !=0)
- scp->result = DID_BAD_TARGET << 16;
- else {
- switch (scp->cmnd[0]) {
- case TEST_UNIT_READY:
- case VERIFY:
- case START_STOP:
- TRACE2(("Test/Verify/Start hdrive %d\n",hdrive));
- break;
-
- case INQUIRY:
- TRACE2(("Inquiry hdrive %d devtype %d\n",
- hdrive,ha->id[b][t].devtype));
- inq.type_qual = (ha->id[b][t].devtype&4) ? TYPE_ROM:TYPE_DISK;
- /* you can here set all disks to removable, if you want to do
- a flush using the ALLOW_MEDIUM_REMOVAL command */
- inq.modif_rmb = ha->id[b][t].devtype&1 ? 0x80:0x00;
- inq.version = 2;
- inq.resp_aenc = 2;
- inq.add_length= 32;
- strcpy(inq.vendor,"ICP ");
- sprintf(inq.product,"Host Drive #%02d",hdrive);
- strcpy(inq.revision," ");
- gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
- break;
-
- case REQUEST_SENSE:
- TRACE2(("Request sense hdrive %d\n",hdrive));
- sd.errorcode = 0x70;
- sd.segno = 0x00;
- sd.key = NO_SENSE;
- sd.info = 0;
- sd.add_length= 0;
- gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
- break;
-
- case MODE_SENSE:
- TRACE2(("Mode sense hdrive %d\n",hdrive));
- memset((char*)&mpd,0,sizeof(gdth_modep_data));
- mpd.hd.data_length = sizeof(gdth_modep_data);
- mpd.hd.dev_par = (ha->id[b][t].devtype&2) ? 0x80:0;
- mpd.hd.bd_length = sizeof(mpd.bd);
- mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
- mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
- mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
- gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
- break;
-
- case READ_CAPACITY:
- TRACE2(("Read capacity hdrive %d\n",hdrive));
- rdc.last_block_no = ntohl(ha->id[b][t].size-1);
- rdc.block_length = ntohl(SECTOR_SIZE);
- gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
- break;
-
- default:
- TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
- break;
- }
- scp->result = DID_OK << 16;
- }
+ scp->cmnd[0],t));
+
+ switch (scp->cmnd[0]) {
+ case TEST_UNIT_READY:
+ case VERIFY:
+ case START_STOP:
+ TRACE2(("Test/Verify/Start hdrive %d\n",t));
+ break;
+
+ case INQUIRY:
+ TRACE2(("Inquiry hdrive %d devtype %d\n",
+ t,ha->hdr[t].devtype));
+ inq.type_qual = (ha->hdr[t].devtype&4) ? TYPE_ROM:TYPE_DISK;
+ /* you can here set all disks to removable, if you want to do
+ a flush using the ALLOW_MEDIUM_REMOVAL command */
+ inq.modif_rmb = ha->hdr[t].devtype&1 ? 0x80:0x00;
+ inq.version = 2;
+ inq.resp_aenc = 2;
+ inq.add_length= 32;
+ strcpy(inq.vendor,"ICP ");
+ sprintf(inq.product,"Host Drive #%02d",t);
+ strcpy(inq.revision," ");
+ gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
+ break;
+
+ case REQUEST_SENSE:
+ TRACE2(("Request sense hdrive %d\n",t));
+ sd.errorcode = 0x70;
+ sd.segno = 0x00;
+ sd.key = NO_SENSE;
+ sd.info = 0;
+ sd.add_length= 0;
+ gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
+ break;
+
+ case MODE_SENSE:
+ TRACE2(("Mode sense hdrive %d\n",t));
+ memset((char*)&mpd,0,sizeof(gdth_modep_data));
+ mpd.hd.data_length = sizeof(gdth_modep_data);
+ mpd.hd.dev_par = (ha->hdr[t].devtype&2) ? 0x80:0;
+ mpd.hd.bd_length = sizeof(mpd.bd);
+ mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
+ mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
+ mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
+ gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
+ break;
+
+ case READ_CAPACITY:
+ TRACE2(("Read capacity hdrive %d\n",t));
+ rdc.last_block_no = ntohl(ha->hdr[t].size-1);
+ rdc.block_length = ntohl(SECTOR_SIZE);
+ gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
+ break;
+
+ default:
+ TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
+ break;
+ }
+ scp->result = DID_OK << 16;
+
+ if (!scp->SCp.have_data_in)
+ scp->SCp.have_data_in++;
+ else
+ return 1;
- restore_flags(*flags);
- scp->scsi_done(scp);
- save_flags(*flags);
- cli();
- return 1;
+ return 0;
}
static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
@@ -1804,25 +2160,26 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
cmdp->u.cache.sg_canz = 0;
} else {
if (scp->cmd_len != 6) {
- cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[2]);
- cmdp->u.cache.BlockCnt= (ulong)ntohs(*(ushort*)&scp->cmnd[7]);
+ cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]);
+ cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]);
} else {
- cmdp->u.cache.BlockNo = ntohl(*(ulong*)&scp->cmnd[0]) & 0x001fffffUL;
+ cmdp->u.cache.BlockNo =
+ ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL;
cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
}
if (scp->use_sg) {
- cmdp->u.cache.DestAddr= -1UL;
+ cmdp->u.cache.DestAddr= 0xffffffff;
sl = (struct scatterlist *)scp->request_buffer;
for (i=0; i<scp->use_sg; ++i,++sl) {
cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.cache.sg_lst[i].sg_len = (ulong)sl->length;
+ cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
}
- cmdp->u.cache.sg_canz = (ulong)i;
+ cmdp->u.cache.sg_canz = (ulong32)i;
#ifdef GDTH_STATISTICS
- if (max_sg < (ulong)i) {
- max_sg = (ulong)i;
+ if (max_sg < (ulong32)i) {
+ max_sg = (ulong32)i;
TRACE3(("GDT: max_sg = %d\n",i));
}
#endif
@@ -1830,9 +2187,10 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
cmdp->u.cache.sg_lst[i].sg_len = 0;
} else {
if (ha->cache_feat & SCATTER_GATHER) {
- cmdp->u.cache.DestAddr = -1UL;
+ cmdp->u.cache.DestAddr = 0xffffffff;
cmdp->u.cache.sg_canz = 1;
- cmdp->u.cache.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
+ cmdp->u.cache.sg_lst[0].sg_ptr =
+ virt_to_bus(scp->request_buffer);
cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
cmdp->u.cache.sg_lst[1].sg_len = 0;
} else {
@@ -1841,12 +2199,12 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
}
}
}
- TRACE(("cache cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
- cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
- cmdp->u.cache.sg_lst[0].sg_ptr,
- cmdp->u.cache.sg_lst[0].sg_len));
- TRACE(("cache cmd: cmd %d blockno. %ld, blockcnt %ld\n",
- cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
+ TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+ cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
+ cmdp->u.cache.sg_lst[0].sg_ptr,
+ cmdp->u.cache.sg_lst[0].sg_len));
+ TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
+ cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
/* evaluate command size, check space */
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
@@ -1858,7 +2216,7 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive)
if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
ha->ic_all_size) {
TRACE2(("gdth_fill_cache() DPMEM overflow\n"));
- gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
+ ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
return 0;
}
}
@@ -1882,7 +2240,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
l = scp->lun;
cmdp = ha->pccb;
TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
- scp->cmnd[0],b,t,l));
+ scp->cmnd[0],b,t,l));
if (ha->type==GDT_EISA && ha->cmd_cnt>0)
return 0;
@@ -1899,61 +2257,73 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
gdth_set_sema0(hanum);
/* fill command */
- cmdp->OpCode = GDT_WRITE; /* always */
- cmdp->BoardNode = LOCALBOARD;
- cmdp->u.raw.reserved = 0;
- cmdp->u.raw.mdisc_time = 0;
- cmdp->u.raw.mcon_time = 0;
- cmdp->u.raw.clen = scp->cmd_len;
- cmdp->u.raw.target = t;
- cmdp->u.raw.lun = l;
- cmdp->u.raw.bus = b;
- cmdp->u.raw.priority = 0;
- cmdp->u.raw.link_p = NULL;
- cmdp->u.raw.sdlen = scp->request_bufflen;
- cmdp->u.raw.sense_len = 16;
- cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
- cmdp->u.raw.direction =
- gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
- memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
+ if (scp->SCp.Status != -1) {
+ cmdp->OpCode = scp->SCp.Status; /* special raw cmd. */
+ cmdp->BoardNode = LOCALBOARD;
+ cmdp->u.raw.direction = (scp->SCp.phase >> 8);
+ TRACE2(("special raw cmd 0x%x param 0x%x\n",
+ cmdp->OpCode, cmdp->u.raw.direction));
+
+ /* evaluate command size */
+ ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
+ } else {
+ cmdp->OpCode = GDT_WRITE; /* always */
+ cmdp->BoardNode = LOCALBOARD;
+ cmdp->u.raw.reserved = 0;
+ cmdp->u.raw.mdisc_time = 0;
+ cmdp->u.raw.mcon_time = 0;
+ cmdp->u.raw.clen = scp->cmd_len;
+ cmdp->u.raw.target = t;
+ cmdp->u.raw.lun = l;
+ cmdp->u.raw.bus = b;
+ cmdp->u.raw.priority = 0;
+ cmdp->u.raw.link_p = NULL;
+ cmdp->u.raw.sdlen = scp->request_bufflen;
+ cmdp->u.raw.sense_len = 16;
+ cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
+ cmdp->u.raw.direction =
+ gdth_direction_tab[scp->cmnd[0]]==DOU ? DATA_OUT : DATA_IN;
+ memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
- if (scp->use_sg) {
- cmdp->u.raw.sdata = -1UL;
- sl = (struct scatterlist *)scp->request_buffer;
- for (i=0; i<scp->use_sg; ++i,++sl) {
- cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
- cmdp->u.raw.sg_lst[i].sg_len = (ulong)sl->length;
- }
- cmdp->u.raw.sg_ranz = (ulong)i;
+ if (scp->use_sg) {
+ cmdp->u.raw.sdata = 0xffffffff;
+ sl = (struct scatterlist *)scp->request_buffer;
+ for (i=0; i<scp->use_sg; ++i,++sl) {
+ cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+ cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
+ }
+ cmdp->u.raw.sg_ranz = (ulong32)i;
#ifdef GDTH_STATISTICS
- if (max_sg < (ulong)i) {
- max_sg = (ulong)i;
- TRACE3(("GDT: max_sg = %d\n",i));
- }
+ if (max_sg < (ulong32)i) {
+ max_sg = (ulong32)i;
+ TRACE3(("GDT: max_sg = %d\n",i));
+ }
#endif
- if (i<GDTH_MAXSG)
- cmdp->u.raw.sg_lst[i].sg_len = 0;
- } else {
- if (ha->raw_feat & SCATTER_GATHER) {
- cmdp->u.raw.sdata = -1UL;
- cmdp->u.raw.sg_ranz= 1;
- cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
- cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
- cmdp->u.raw.sg_lst[1].sg_len = 0;
+ if (i<GDTH_MAXSG)
+ cmdp->u.raw.sg_lst[i].sg_len = 0;
} else {
- cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer);
- cmdp->u.raw.sg_ranz= 0;
+ if (ha->raw_feat & SCATTER_GATHER) {
+ cmdp->u.raw.sdata = 0xffffffff;
+ cmdp->u.raw.sg_ranz= 1;
+ cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
+ cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
+ cmdp->u.raw.sg_lst[1].sg_len = 0;
+ } else {
+ cmdp->u.raw.sdata = virt_to_bus(scp->request_buffer);
+ cmdp->u.raw.sg_ranz= 0;
+ }
}
- }
- TRACE(("raw cmd: addr. %lx sganz %lx sgptr0 %lx sglen0 %lx\n",
- cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
- cmdp->u.raw.sg_lst[0].sg_ptr,
- cmdp->u.raw.sg_lst[0].sg_len));
+ TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+ cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
+ cmdp->u.raw.sg_lst[0].sg_ptr,
+ cmdp->u.raw.sg_lst[0].sg_len));
- /* evaluate command size, check space */
- ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
- (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
+ /* evaluate command size */
+ ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
+ (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
+ }
+ /* check space */
if (ha->cmd_len & 3)
ha->cmd_len += (4 - (ha->cmd_len & 3));
@@ -1961,7 +2331,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
ha->ic_all_size) {
TRACE2(("gdth_fill_raw() DPMEM overflow\n"));
- gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
+ ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
return 0;
}
}
@@ -1971,7 +2341,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
return cmd_index;
}
-static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
+static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp)
{
register gdth_ha_str *ha;
register gdth_cmd_str *cmdp;
@@ -2000,13 +2370,16 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
/* evaluate command size, check space */
if (cmdp->OpCode == GDT_IOCTL) {
TRACE2(("IOCTL\n"));
- ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong);
+ ha->cmd_len =
+ GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32);
} else if (cmdp->Service == CACHESERVICE) {
TRACE2(("cache command %d\n",cmdp->OpCode));
- ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
+ ha->cmd_len =
+ GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
} else if (cmdp->Service == SCSIRAWSERVICE) {
TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0]));
- ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
+ ha->cmd_len =
+ GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
}
if (ha->cmd_len & 3)
@@ -2016,7 +2389,7 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
if ((ha->cmd_offs_dpmem + ha->cmd_len + DPMEM_COMMAND_OFFSET) >
ha->ic_all_size) {
TRACE2(("gdth_special_cmd() DPMEM overflow\n"));
- gdth_cmd_tab[cmd_index-2][hanum].cmnd = UNUSED_CMND;
+ ha->cmd_tab[cmd_index-2].cmnd = UNUSED_CMND;
return 0;
}
}
@@ -2028,8 +2401,8 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
/* Controller event handling functions */
-static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
- gdth_evt_data *evt)
+static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source,
+ ushort idx, gdth_evt_data *evt)
{
gdth_evt_str *e;
ulong flags;
@@ -2039,8 +2412,7 @@ static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
if (source == 0) /* no source -> no event */
return 0;
- save_flags(flags);
- cli();
+ GDTH_LOCK_HA(ha, flags);
if (ebuffer[elastidx].event_source == source &&
ebuffer[elastidx].event_idx == idx &&
!memcmp((char *)&ebuffer[elastidx].event_data.eu,
@@ -2068,19 +2440,18 @@ static gdth_evt_str *gdth_store_event(ushort source, ushort idx,
e->same_count = 1;
e->event_data = *evt;
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
return e;
}
-static int gdth_read_event(int handle, gdth_evt_str *estr)
+static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr)
{
gdth_evt_str *e;
int eindex;
ulong flags;
TRACE2(("gdth_read_event() handle %d\n", handle));
- save_flags(flags);
- cli();
+ GDTH_LOCK_HA(ha, flags);
if (handle == -1)
eindex = eoldidx;
else
@@ -2088,7 +2459,7 @@ static int gdth_read_event(int handle, gdth_evt_str *estr)
estr->event_source = 0;
if (eindex >= MAX_EVENTS) {
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
return eindex;
}
e = &ebuffer[eindex];
@@ -2101,11 +2472,12 @@ static int gdth_read_event(int handle, gdth_evt_str *estr)
}
memcpy(estr, e, sizeof(gdth_evt_str));
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
return eindex;
}
-static void gdth_readapp_event(unchar application, gdth_evt_str *estr)
+static void gdth_readapp_event(gdth_ha_str *ha,
+ unchar application, gdth_evt_str *estr)
{
gdth_evt_str *e;
int eindex;
@@ -2113,8 +2485,7 @@ static void gdth_readapp_event(unchar application, gdth_evt_str *estr)
unchar found = FALSE;
TRACE2(("gdth_readapp_event() app. %d\n", application));
- save_flags(flags);
- cli();
+ GDTH_LOCK_HA(ha, flags);
eindex = eoldidx;
for (;;) {
e = &ebuffer[eindex];
@@ -2134,35 +2505,21 @@ static void gdth_readapp_event(unchar application, gdth_evt_str *estr)
memcpy(estr, e, sizeof(gdth_evt_str));
else
estr->event_source = 0;
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
}
static void gdth_clear_events()
{
- ulong flags;
-
TRACE(("gdth_clear_events()"));
- save_flags(flags);
- cli();
eoldidx = elastidx = 0;
ebuffer[0].event_source = 0;
- restore_flags(flags);
}
/* SCSI interface functions */
#if LINUX_VERSION_CODE >= 0x010346
-static void do_gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&io_request_lock, flags);
- gdth_interrupt(irq, dev_id, regs);
- spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
#else
static void gdth_interrupt(int irq,struct pt_regs *regs)
@@ -2173,11 +2530,12 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
gdt6_dpram_str *dp6_ptr;
gdt2_dpram_str *dp2_ptr;
Scsi_Cmnd *scp;
- int hanum;
+ int hanum, rval;
unchar IStatus;
ushort CmdStatus, Service = 0;
- ulong InfoBytes, InfoBytes2 = 0;
+ ulong32 InfoBytes, InfoBytes2 = 0;
gdth_evt_data dvr;
+ ulong flags = 0;
TRACE(("gdth_interrupt() IRQ %d\n",irq));
@@ -2188,6 +2546,8 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
}
}
+ if (!gdth_polling)
+ GDTH_LOCK_HA((gdth_ha_str *)dev_id,flags);
wait_index = 0;
/* search controller */
@@ -2195,6 +2555,8 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
/*
TRACE2(("gdth_interrupt(): Spurious interrupt received\n"));
*/
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
return;
}
@@ -2204,63 +2566,63 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
ha = HADATA(gdth_ctr_tab[hanum]);
if (ha->type == GDT_EISA) {
- if (IStatus & 0x80) { /* error flag */
+ if (IStatus & 0x80) { /* error flag */
IStatus &= ~0x80;
CmdStatus = inw(ha->bmic + MAILBOXREG+8);
TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
- if (IStatus == ASYNCINDEX) { /* async. event ? */
+ if (IStatus == ASYNCINDEX) { /* async. event ? */
Service = inw(ha->bmic + MAILBOXREG+10);
InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
}
- } else /* no error */
+ } else /* no error */
CmdStatus = S_OK;
InfoBytes = inl(ha->bmic + MAILBOXREG+12);
- if (gdth_polling) /* init. -> more info */
- InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
- outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */
- outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */
+ if (gdth_polling) /* init. -> more info */
+ InfoBytes2 = inl(ha->bmic + MAILBOXREG+4);
+ outb(0xff, ha->bmic + EDOORREG); /* acknowledge interrupt */
+ outb(0x00, ha->bmic + SEMA1REG); /* reset status semaphore */
} else if (ha->type == GDT_ISA) {
dp2_ptr = (gdt2_dpram_str *)ha->brd;
- if (IStatus & 0x80) { /* error flag */
+ if (IStatus & 0x80) { /* error flag */
IStatus &= ~0x80;
- CmdStatus = readw(&dp2_ptr->u.ic.Status);
+ CmdStatus = gdth_readw(&dp2_ptr->u.ic.Status);
TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
- if (IStatus == ASYNCINDEX) { /* async. event ? */
- Service = readw(&dp2_ptr->u.ic.Service);
- InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
+ if (IStatus == ASYNCINDEX) { /* async. event ? */
+ Service = gdth_readw(&dp2_ptr->u.ic.Service);
+ InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
}
- } else /* no error */
+ } else /* no error */
CmdStatus = S_OK;
- InfoBytes = readl(&dp2_ptr->u.ic.Info[0]);
- if (gdth_polling) /* init. -> more info */
- InfoBytes2 = readl(&dp2_ptr->u.ic.Info[1]);
- writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
- writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */
- writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */
+ InfoBytes = gdth_readl(&dp2_ptr->u.ic.Info[0]);
+ if (gdth_polling) /* init. -> more info */
+ InfoBytes2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
+ gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
+ gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); /* reset command index */
+ gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */
} else if (ha->type == GDT_PCI) {
dp6_ptr = (gdt6_dpram_str *)ha->brd;
- if (IStatus & 0x80) { /* error flag */
+ if (IStatus & 0x80) { /* error flag */
IStatus &= ~0x80;
- CmdStatus = readw(&dp6_ptr->u.ic.Status);
+ CmdStatus = gdth_readw(&dp6_ptr->u.ic.Status);
TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
if (IStatus == ASYNCINDEX) { /* async. event ? */
- Service = readw(&dp6_ptr->u.ic.Service);
- InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
+ Service = gdth_readw(&dp6_ptr->u.ic.Service);
+ InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
}
- } else /* no error */
+ } else /* no error */
CmdStatus = S_OK;
- InfoBytes = readl(&dp6_ptr->u.ic.Info[0]);
- if (gdth_polling) /* init. -> more info */
- InfoBytes2 = readl(&dp6_ptr->u.ic.Info[1]);
- writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
- writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */
- writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */
+ InfoBytes = gdth_readl(&dp6_ptr->u.ic.Info[0]);
+ if (gdth_polling) /* init. -> more info */
+ InfoBytes2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
+ gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
+ gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); /* reset command index */
+ gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */
} else if (ha->type == GDT_PCINEW) {
- if (IStatus & 0x80) { /* error flag */
+ if (IStatus & 0x80) { /* error flag */
IStatus &= ~0x80;
CmdStatus = inw(PTR2USHORT(&ha->plx->status));
TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
- if (IStatus == ASYNCINDEX) { /* async. event ? */
+ if (IStatus == ASYNCINDEX) { /* async. event ? */
Service = inw(PTR2USHORT(&ha->plx->service));
InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
}
@@ -2268,34 +2630,36 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
CmdStatus = S_OK;
InfoBytes = inl(PTR2USHORT(&ha->plx->info[0]));
- if (gdth_polling) /* init. -> more info */
- InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
+ if (gdth_polling) /* init. -> more info */
+ InfoBytes2 = inl(PTR2USHORT(&ha->plx->info[1]));
outb(0xff, PTR2USHORT(&ha->plx->edoor_reg));
outb(0x00, PTR2USHORT(&ha->plx->sema1_reg));
} else if (ha->type == GDT_PCIMPR) {
dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
- if (IStatus & 0x80) { /* error flag */
+ if (IStatus & 0x80) { /* error flag */
IStatus &= ~0x80;
- CmdStatus = readw(&dp6m_ptr->i960r.status);
+ CmdStatus = gdth_readw(&dp6m_ptr->i960r.status);
TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,CmdStatus));
- if (IStatus == ASYNCINDEX) { /* async. event ? */
- Service = readw(&dp6m_ptr->i960r.service);
- InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
+ if (IStatus == ASYNCINDEX) { /* async. event ? */
+ Service = gdth_readw(&dp6m_ptr->i960r.service);
+ InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
}
- } else /* no error */
+ } else /* no error */
CmdStatus = S_OK;
- InfoBytes = readl(&dp6m_ptr->i960r.info[0]);
- if (gdth_polling) /* init. -> more info */
- InfoBytes2 = readl(&dp6m_ptr->i960r.info[1]);
- writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
- writeb(0, &dp6m_ptr->i960r.sema1_reg);
+ InfoBytes = gdth_readl(&dp6m_ptr->i960r.info[0]);
+ if (gdth_polling) /* init. -> more info */
+ InfoBytes2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+ gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+ gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
} else {
TRACE2(("gdth_interrupt() unknown controller type\n"));
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
return;
}
- TRACE(("gdth_interrupt() index %d stat %d info %ld\n",
- IStatus,CmdStatus,InfoBytes));
+ TRACE(("gdth_interrupt() index %d stat %d info %d\n",
+ IStatus,CmdStatus,InfoBytes));
ha->status = CmdStatus;
ha->info = InfoBytes;
ha->info2 = InfoBytes2;
@@ -2308,31 +2672,51 @@ static void gdth_interrupt(int irq,struct pt_regs *regs)
if (IStatus == ASYNCINDEX) {
TRACE2(("gdth_interrupt() async. event\n"));
gdth_async_event(hanum,Service);
- } else {
- if (IStatus == SPEZINDEX) {
- TRACE2(("Service unknown or not initialized !\n"));
- dvr.size = sizeof(dvr.eu.driver);
- dvr.eu.driver.ionode = hanum;
- gdth_store_event(ES_DRIVER, 4, &dvr);
- return;
- }
- scp = gdth_cmd_tab[IStatus-2][hanum].cmnd;
- Service = gdth_cmd_tab[IStatus-2][hanum].service;
- gdth_cmd_tab[IStatus-2][hanum].cmnd = UNUSED_CMND;
- if (scp == UNUSED_CMND) {
- TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
- dvr.size = sizeof(dvr.eu.driver);
- dvr.eu.driver.ionode = hanum;
- dvr.eu.driver.index = IStatus;
- gdth_store_event(ES_DRIVER, 1, &dvr);
- return;
- }
- if (scp == INTERNAL_CMND) {
- TRACE(("gdth_interrupt() answer to internal command\n"));
- return;
- }
- TRACE(("gdth_interrupt() sync. status\n"));
- gdth_sync_event(hanum,Service,IStatus,scp);
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ gdth_next(hanum);
+ return;
+ }
+
+ if (IStatus == SPEZINDEX) {
+ TRACE2(("Service unknown or not initialized !\n"));
+ dvr.size = sizeof(dvr.eu.driver);
+ dvr.eu.driver.ionode = hanum;
+ gdth_store_event(ha, ES_DRIVER, 4, &dvr);
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ return;
+ }
+ scp = ha->cmd_tab[IStatus-2].cmnd;
+ Service = ha->cmd_tab[IStatus-2].service;
+ ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
+ if (scp == UNUSED_CMND) {
+ TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
+ dvr.size = sizeof(dvr.eu.driver);
+ dvr.eu.driver.ionode = hanum;
+ dvr.eu.driver.index = IStatus;
+ gdth_store_event(ha, ES_DRIVER, 1, &dvr);
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ return;
+ }
+ if (scp == INTERNAL_CMND) {
+ TRACE(("gdth_interrupt() answer to internal command\n"));
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ return;
+ }
+
+ TRACE(("gdth_interrupt() sync. status\n"));
+ rval = gdth_sync_event(hanum,Service,IStatus,scp);
+ if (!gdth_polling)
+ GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+ if (rval == 2) {
+ gdth_putq(hanum,scp,scp->SCp.this_residual);
+ } else if (rval == 1) {
+ GDTH_LOCK_SCSI_DONE(flags);
+ scp->scsi_done(scp);
+ GDTH_UNLOCK_SCSI_DONE(flags);
}
gdth_next(hanum);
}
@@ -2348,13 +2732,14 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
ha = HADATA(gdth_ctr_tab[hanum]);
cmdp = ha->pccb;
- TRACE(("gdth_sync_event() scp %lx serv %d status %d\n",
- (ulong)scp,service,ha->status));
+ TRACE(("gdth_sync_event() serv %d status %d\n",
+ service,ha->status));
if (service == SCREENSERVICE) {
msg = (gdth_msg_str *)ha->pscratch;
- TRACE(("len: %ld, answer: %d, ext: %d, alen: %ld\n",
- msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
+ ha->scratch_busy = FALSE;
+ TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
+ msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
if (msg->msg_len)
if (!(msg->msg_answer && msg->msg_ext)) {
msg->msg_text[msg->msg_len] = '\0';
@@ -2363,7 +2748,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
if (msg->msg_ext && !msg->msg_answer) {
while (gdth_test_busy(hanum))
- udelay(1);
+ gdth_delay(0);
cmdp->Service = SCREENSERVICE;
cmdp->RequestBuffer = SCREEN_CMND;
gdth_get_cmd_index(hanum);
@@ -2372,14 +2757,15 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
cmdp->BoardNode = LOCALBOARD;
cmdp->u.screen.reserved = 0;
cmdp->u.screen.msg_handle= msg->msg_handle;
- cmdp->u.screen.msg_addr = (ulong)msg;
+ cmdp->u.screen.msg_addr = virt_to_bus(msg);
+ ha->scratch_busy = TRUE;
ha->cmd_offs_dpmem = 0;
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr)
- + sizeof(ulong);
+ + sizeof(ulong32);
ha->cmd_cnt = 0;
gdth_copy_command(hanum);
gdth_release_event(hanum);
- return 1;
+ return 0;
}
if (msg->msg_answer && msg->msg_alen) {
@@ -2400,7 +2786,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
}
msg->msg_len = i;
while (gdth_test_busy(hanum))
- udelay(1);
+ gdth_delay(0);
cmdp->Service = SCREENSERVICE;
cmdp->RequestBuffer = SCREEN_CMND;
gdth_get_cmd_index(hanum);
@@ -2409,14 +2795,15 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
cmdp->BoardNode = LOCALBOARD;
cmdp->u.screen.reserved = 0;
cmdp->u.screen.msg_handle= msg->msg_handle;
- cmdp->u.screen.msg_addr = (ulong)msg;
+ cmdp->u.screen.msg_addr = virt_to_bus(msg);
+ ha->scratch_busy = TRUE;
ha->cmd_offs_dpmem = 0;
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr)
- + sizeof(ulong);
+ + sizeof(ulong32);
ha->cmd_cnt = 0;
gdth_copy_command(hanum);
gdth_release_event(hanum);
- return 1;
+ return 0;
}
printk("\n");
@@ -2424,12 +2811,25 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
scp->SCp.Message = (int)ha->status;
/* cache or raw service */
if (ha->status == S_OK) {
+ if (scp->SCp.Status != -1) {
+ TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n",
+ scp->SCp.Status));
+ scp->SCp.Status = -1;
+ scp->SCp.this_residual = HIGH_PRI;
+ return 2;
+ }
scp->result = DID_OK << 16;
} else if (ha->status == S_BSY) {
TRACE2(("Controller busy -> retry !\n"));
- gdth_putq(hanum,scp,DEFAULT_PRI);
- return 1;
+ return 2;
} else {
+ if (scp->SCp.Status != -1) {
+ TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n",
+ scp->SCp.Status, ha->status));
+ scp->SCp.Status = -1;
+ scp->SCp.this_residual = HIGH_PRI;
+ return 2;
+ }
if (service == CACHESERVICE) {
memset((char*)scp->sense_buffer,0,16);
scp->sense_buffer[0] = 0x70;
@@ -2442,30 +2842,27 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
dvr.eu.sync.service = service;
dvr.eu.sync.status = ha->status;
dvr.eu.sync.info = ha->info;
- dvr.eu.sync.hostdrive =
-#if LINUX_VERSION_CODE >= 0x020000
- ha->id[scp->channel][scp->target].hostdrive;
-#else
- ha->id[NUMDATA(scp->host)->busnum][scp->target].hostdrive;
-#endif
+ dvr.eu.sync.hostdrive = scp->target;
if (ha->status >= 0x8000)
- gdth_store_event(ES_SYNC, 0, &dvr);
+ gdth_store_event(ha, ES_SYNC, 0, &dvr);
else
- gdth_store_event(ES_SYNC, service, &dvr);
+ gdth_store_event(ha, ES_SYNC, service, &dvr);
}
} else {
- if (ha->status!=S_RAW_SCSI || ha->status==S_RAW_ILL) {
+ if (ha->status!=S_RAW_SCSI || ha->info>=0x100) {
scp->result = DID_BAD_TARGET << 16;
} else {
scp->result = (DID_OK << 16) | ha->info;
}
}
}
- scp->SCp.have_data_in++;
- scp->scsi_done(scp);
+ if (!scp->SCp.have_data_in)
+ scp->SCp.have_data_in++;
+ else
+ return 1;
}
- return 1;
+ return 0;
}
static char *async_cache_tab[] = {
@@ -2587,15 +2984,40 @@ static char *async_cache_tab[] = {
"GDT HA %u, Array Drive %u: expand restarted",
/*58*/ "\005\000\002\006\002"
"GDT HA %u, Array Drive %u: expand stopped",
+/*59*/ "\005\000\002\010\002"
+ "GDT HA %u, Mirror Drive %u: drive build quited",
+/*60*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: parity build quited",
+/*61*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: drive rebuild quited",
+/*62*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: parity verify started",
+/*63*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: parity verify done",
+/*64*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: parity verify failed",
+/*65*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: parity error detected",
+/*66*/ "\005\000\002\006\002"
+ "GDT HA %u, Array Drive %u: parity verify quited",
+/*67*/ "\005\000\002\006\002"
+ "GDT HA %u, Host Drive %u reserved",
+/*68*/ "\005\000\002\006\002"
+ "GDT HA %u, Host Drive %u mounted and released",
+/*69*/ "\005\000\002\006\002"
+ "GDT HA %u, Host Drive %u released",
+/*70*/ "\003\000\002"
+ "GDT HA %u, DRAM error detected and corrected with ECC",
+/*71*/ "\003\000\002"
+ "GDT HA %u, Uncorrectable DRAM error detected with ECC",
+/*72*/ "\011\000\002\012\001\013\001\014\001"
+ "GDT HA %u, SCSI bus %u, ID %u, LUN %u: reassigning block",
};
static int gdth_async_event(int hanum,int service)
{
- gdth_stackframe stack;
gdth_evt_data dvr;
- char *f = NULL;
- int i,j;
gdth_ha_str *ha;
gdth_msg_str *msg;
gdth_cmd_str *cmdp;
@@ -2605,12 +3027,12 @@ static int gdth_async_event(int hanum,int service)
cmdp= ha->pccb;
msg = (gdth_msg_str *)ha->pscratch;
TRACE2(("gdth_async_event() ha %d serv %d\n",
- hanum,service));
+ hanum,service));
if (service == SCREENSERVICE) {
if (ha->status == MSG_REQUEST) {
while (gdth_test_busy(hanum))
- udelay(1);
+ gdth_delay(0);
cmdp->Service = SCREENSERVICE;
cmdp->RequestBuffer = SCREEN_CMND;
cmd_index = gdth_get_cmd_index(hanum);
@@ -2619,10 +3041,11 @@ static int gdth_async_event(int hanum,int service)
cmdp->BoardNode = LOCALBOARD;
cmdp->u.screen.reserved = 0;
cmdp->u.screen.msg_handle= MSG_INV_HANDLE;
- cmdp->u.screen.msg_addr = (ulong)msg;
+ cmdp->u.screen.msg_addr = virt_to_bus(msg);
+ ha->scratch_busy = TRUE;
ha->cmd_offs_dpmem = 0;
ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.msg_addr)
- + sizeof(ulong);
+ + sizeof(ulong32);
ha->cmd_cnt = 0;
gdth_copy_command(hanum);
if (ha->type == GDT_EISA)
@@ -2641,80 +3064,89 @@ static int gdth_async_event(int hanum,int service)
dvr.eu.async.service = service;
dvr.eu.async.status = ha->status;
dvr.eu.async.info = ha->info;
- *(ulong *)dvr.eu.async.scsi_coord = ha->info2;
- gdth_store_event(ES_ASYNC, service, &dvr);
+ *(ulong32 *)dvr.eu.async.scsi_coord = ha->info2;
+ gdth_store_event(ha, ES_ASYNC, service, &dvr);
+ gdth_log_event( &dvr );
+ }
+ return 1;
+}
- if (service==CACHESERVICE && INDEX_OK(ha->status,async_cache_tab)) {
- TRACE2(("GDT: Async. event cache service, event no.: %d\n",
- ha->status));
-
- f = async_cache_tab[ha->status];
+static void gdth_log_event(gdth_evt_data *dvr)
+{
+ gdth_stackframe stack;
+ char *f = NULL;
+ int i,j;
- /* i: parameter to push, j: stack element to fill */
- for (j=0,i=1; i < f[0]; i+=2) {
- switch (f[i+1]) {
- case 4:
- stack.b[j++] = *(ulong*)&dvr.eu.stream[(int)f[i]];
- break;
- case 2:
- stack.b[j++] = *(ushort*)&dvr.eu.stream[(int)f[i]];
- break;
- case 1:
- stack.b[j++] = *(unchar*)&dvr.eu.stream[(int)f[i]];
- break;
- default:
- break;
- }
+ TRACE2(("gdth_log_event()\n"));
+ if (dvr->eu.async.service == CACHESERVICE &&
+ INDEX_OK(dvr->eu.async.status, async_cache_tab)) {
+ TRACE2(("GDT: Async. event cache service, event no.: %d\n",
+ dvr->eu.async.status));
+
+ f = async_cache_tab[dvr->eu.async.status];
+
+ /* i: parameter to push, j: stack element to fill */
+ for (j=0,i=1; i < f[0]; i+=2) {
+ switch (f[i+1]) {
+ case 4:
+ stack.b[j++] = *(ulong32*)&dvr->eu.stream[(int)f[i]];
+ break;
+ case 2:
+ stack.b[j++] = *(ushort*)&dvr->eu.stream[(int)f[i]];
+ break;
+ case 1:
+ stack.b[j++] = *(unchar*)&dvr->eu.stream[(int)f[i]];
+ break;
+ default:
+ break;
}
+ }
- printk(&f[f[0]],stack); printk("\n");
+ printk(&f[(int)f[0]],stack); printk("\n");
- } else {
- printk("GDT: Unknown async. event service %d event no. %d\n",
- service,ha->status);
- }
+ } else {
+ printk("GDT: Unknown async. event service %d event no. %d\n",
+ dvr->eu.async.service,dvr->eu.async.status);
}
- return 1;
}
#ifdef GDTH_STATISTICS
-void gdth_timeout(void)
+void gdth_timeout(ulong data)
{
- ulong flags,i;
+ ulong32 i;
Scsi_Cmnd *nscp;
gdth_ha_str *ha;
+ ulong flags;
int hanum = 0;
- save_flags(flags);
- cli();
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i)
- if (gdth_cmd_tab[i][hanum].cmnd != UNUSED_CMND)
+ if (ha->cmd_tab[i].cmnd != UNUSED_CMND)
++act_stats;
- ha = HADATA(gdth_ctr_tab[hanum]);
for (act_rq=0,nscp=ha->req_first; nscp; nscp=(Scsi_Cmnd*)nscp->SCp.ptr)
++act_rq;
- TRACE2(("gdth_to(): ints %ld, ios %ld, act_stats %ld, act_rq %ld\n",
+ TRACE2(("gdth_to(): ints %d, ios %d, act_stats %d, act_rq %d\n",
act_ints, act_ios, act_stats, act_rq));
act_ints = act_ios = 0;
- timer_table[GDTH_TIMER].expires = jiffies + 30*HZ;
- timer_active |= 1<<GDTH_TIMER;
- restore_flags(flags);
+ gdth_timer.expires = jiffies + 30 * HZ;
+ add_timer(&gdth_timer);
+ GDTH_UNLOCK_HA(ha, flags);
}
#endif
-int gdth_detect(Scsi_Host_Template *shtp)
+
+__initfunc (int gdth_detect(Scsi_Host_Template *shtp))
{
struct Scsi_Host *shp;
gdth_ha_str *ha;
- unsigned long flags;
- ulong isa_bios;
- ushort eisa_slot,device_id,index;
- gdth_pci_str pcistr;
- int i,j,hanum;
+ ulong32 isa_bios;
+ ushort eisa_slot;
+ int i,hanum,cnt,ctr;
unchar b;
@@ -2731,28 +3163,24 @@ int gdth_detect(Scsi_Host_Template *shtp)
#else
printk("Console\n");
#endif
- WAITSEC(3);
+ gdth_delay(3000);
#endif
TRACE(("gdth_detect()\n"));
- if (disable_gdth_scan) {
+ if (disable) {
printk("GDT: Controller driver disabled from command line !\n");
return 0;
}
/* initializations */
gdth_polling = TRUE; b = 0;
- for (i=0; i<GDTH_MAXCMDS; ++i)
- for (j=0; j<MAXHA; ++j)
- gdth_cmd_tab[i][j].cmnd = UNUSED_CMND;
- for (i=0; i<4; ++i)
- for (j=0; j<MAXHA; ++j)
- gdth_ioctl_tab[i][j] = NULL;
gdth_clear_events();
/* scanning for controllers, at first: ISA controller */
for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
+ if (gdth_ctr_count >= MAXHA)
+ break;
if (gdth_search_isa(isa_bios)) { /* controller found */
shp = scsi_register(shtp,sizeof(gdth_ext_str));
ha = HADATA(shp);
@@ -2761,19 +3189,16 @@ int gdth_detect(Scsi_Host_Template *shtp)
continue;
}
/* controller found and initialized */
- printk("Configuring GDT-ISA HA at BIOS 0x%05lX IRQ %u DRQ %u\n",
+ printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
isa_bios,ha->irq,ha->drq);
- save_flags(flags);
- cli();
#if LINUX_VERSION_CODE >= 0x010346
- if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
+ if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
#else
if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
#endif
{
printk("GDT-ISA: Unable to allocate IRQ\n");
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
@@ -2784,7 +3209,6 @@ int gdth_detect(Scsi_Host_Template *shtp)
#else
free_irq(ha->irq);
#endif
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
@@ -2793,12 +3217,6 @@ int gdth_detect(Scsi_Host_Template *shtp)
shp->unchecked_isa_dma = 1;
shp->irq = ha->irq;
shp->dma_channel = ha->drq;
- for (i=0; i<MAXID; ++i) {
- if (ha->id[0][i].type==SIOP_DTYP) {
- shp->this_id = i;
- break;
- }
- }
hanum = gdth_ctr_count;
gdth_ctr_tab[gdth_ctr_count++] = shp;
gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
@@ -2807,61 +3225,56 @@ int gdth_detect(Scsi_Host_Template *shtp)
NUMDATA(shp)->busnum= 0;
ha->pccb = CMDDATA(shp);
- ha->pscratch = DMADATA(shp);
+ ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+ ha->scratch_busy = FALSE;
ha->req_first = NULL;
- for (i=0; i<MAXBUS; ++i) {
- for (j=0; j<MAXID; ++j) {
- ha->id[i][j].type = EMPTY_DTYP;
- ha->id[i][j].lock = 0;
- }
- }
- restore_flags(flags);
-
- if (!gdth_search_drives(hanum)) {
+ ha->tid_cnt = MAX_HDRIVES;
+ if (max_ids > 0 && max_ids < ha->tid_cnt)
+ ha->tid_cnt = max_ids;
+ for (i=0; i<GDTH_MAXCMDS; ++i)
+ ha->cmd_tab[i].cmnd = UNUSED_CMND;
+ ha->scan_mode = rescan ? 0x10 : 0;
+
+ if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
printk("GDT-ISA: Error during device scan\n");
--gdth_ctr_count;
- --gdth_ctr_vcount;
- save_flags(flags);
- cli();
+ --gdth_ctr_vcount;
+ if (ha->pscratch != NULL)
+ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
#if LINUX_VERSION_CODE >= 0x010346
free_irq(ha->irq,NULL);
#else
free_irq(ha->irq);
#endif
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
#if LINUX_VERSION_CODE >= 0x020000
- shp->max_id = 8;
- shp->max_lun = 8;
- shp->max_channel = ha->bus_cnt - 1;
+ shp->max_id = ha->tid_cnt;
+ shp->max_lun = MAXLUN;
+ shp->max_channel = ha->bus_cnt;
#else
/* register addit. SCSI channels as virtual controllers */
- for (b=1; b<ha->bus_cnt; ++b) {
+ for (b=1; b<ha->bus_cnt+1; ++b) {
shp = scsi_register(shtp,sizeof(gdth_num_str));
shp->unchecked_isa_dma = 1;
shp->irq = ha->irq;
shp->dma_channel = ha->drq;
- for (i=0; i<MAXID; ++i) {
- if (ha->id[b][i].type==SIOP_DTYP) {
- shp->this_id = i;
- break;
- }
- }
gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
NUMDATA(shp)->hanum = (ushort)hanum;
NUMDATA(shp)->busnum = b;
}
#endif
-
+ GDTH_INIT_LOCK_HA(ha);
gdth_enable_int(hanum);
}
}
/* scanning for EISA controllers */
for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
+ if (gdth_ctr_count >= MAXHA)
+ break;
if (gdth_search_eisa(eisa_slot)) { /* controller found */
shp = scsi_register(shtp,sizeof(gdth_ext_str));
ha = HADATA(shp);
@@ -2873,134 +3286,117 @@ int gdth_detect(Scsi_Host_Template *shtp)
printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
eisa_slot>>12,ha->irq);
- save_flags(flags);
- cli();
#if LINUX_VERSION_CODE >= 0x010346
- if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
+ if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
#else
if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
#endif
{
printk("GDT-EISA: Unable to allocate IRQ\n");
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
shp->unchecked_isa_dma = 0;
shp->irq = ha->irq;
shp->dma_channel = 0xff;
- for (i=0; i<MAXID; ++i) {
- if (ha->id[0][i].type==SIOP_DTYP) {
- shp->this_id = i;
- break;
- }
- }
hanum = gdth_ctr_count;
gdth_ctr_tab[gdth_ctr_count++] = shp;
gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
NUMDATA(shp)->hanum = (ushort)hanum;
NUMDATA(shp)->busnum= 0;
- TRACE2(("EISA detect Bus 0: shp %lx hanum %d\n",
- (ulong)shp,NUMDATA(shp)->hanum));
+ TRACE2(("EISA detect Bus 0: hanum %d\n",
+ NUMDATA(shp)->hanum));
ha->pccb = CMDDATA(shp);
- ha->pscratch = DMADATA(shp);
+ ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+ ha->scratch_busy = FALSE;
ha->req_first = NULL;
- for (i=0; i<MAXBUS; ++i) {
- for (j=0; j<MAXID; ++j) {
- ha->id[i][j].type = EMPTY_DTYP;
- ha->id[i][j].lock = 0;
- }
- }
- restore_flags(flags);
-
- if (!gdth_search_drives(hanum)) {
+ ha->tid_cnt = MAX_HDRIVES;
+ if (max_ids > 0 && max_ids < ha->tid_cnt)
+ ha->tid_cnt = max_ids;
+ for (i=0; i<GDTH_MAXCMDS; ++i)
+ ha->cmd_tab[i].cmnd = UNUSED_CMND;
+ ha->scan_mode = rescan ? 0x10 : 0;
+
+ if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
printk("GDT-EISA: Error during device scan\n");
--gdth_ctr_count;
- --gdth_ctr_vcount;
- save_flags(flags);
- cli();
+ --gdth_ctr_vcount;
+ if (ha->pscratch != NULL)
+ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
#if LINUX_VERSION_CODE >= 0x010346
free_irq(ha->irq,NULL);
#else
free_irq(ha->irq);
#endif
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
#if LINUX_VERSION_CODE >= 0x020000
- shp->max_id = 8;
- shp->max_lun = 8;
- shp->max_channel = ha->bus_cnt - 1;
+ shp->max_id = ha->tid_cnt;
+ shp->max_lun = MAXLUN;
+ shp->max_channel = ha->bus_cnt;
#else
/* register addit. SCSI channels as virtual controllers */
- for (b=1; b<ha->bus_cnt; ++b) {
+ for (b=1; b<ha->bus_cnt+1; ++b) {
shp = scsi_register(shtp,sizeof(gdth_num_str));
shp->unchecked_isa_dma = 0;
shp->irq = ha->irq;
shp->dma_channel = 0xff;
- for (i=0; i<MAXID; ++i) {
- if (ha->id[b][i].type==SIOP_DTYP) {
- shp->this_id = i;
- break;
- }
- }
gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
NUMDATA(shp)->hanum = (ushort)hanum;
NUMDATA(shp)->busnum = b;
- TRACE2(("EISA detect Bus %d: shp %lx hanum %d\n",
- NUMDATA(shp)->busnum,(ulong)shp,
- NUMDATA(shp)->hanum));
+ TRACE2(("EISA detect Bus %d: shp %x hanum %d\n",
+ NUMDATA(shp)->busnum,(ulong32)shp,
+ NUMDATA(shp)->hanum));
}
#endif
-
+ GDTH_INIT_LOCK_HA(ha);
gdth_enable_int(hanum);
}
}
/* scanning for PCI controllers */
- for (device_id = 0; device_id <= PCI_DEVICE_ID_VORTEX_GDT6x21RP2; ++device_id) {
- if (device_id > PCI_DEVICE_ID_VORTEX_GDT6555 &&
- device_id < PCI_DEVICE_ID_VORTEX_GDT6x17RP)
- continue;
- for (index = 0; ; ++index) {
- if (!gdth_search_pci(device_id,index,&pcistr))
- break; /* next device_id */
+#if LINUX_VERSION_CODE >= 0x2015C
+ if (pci_present())
+#else
+ if (pcibios_present())
+#endif
+ {
+ gdth_pci_str pcistr[MAXHA];
+
+ cnt = gdth_search_pci(pcistr);
+ gdth_sort_pci(pcistr,cnt);
+ for (ctr = 0; ctr < cnt; ++ctr) {
+ if (gdth_ctr_count >= MAXHA)
+ break;
shp = scsi_register(shtp,sizeof(gdth_ext_str));
ha = HADATA(shp);
- if (!gdth_init_pci(&pcistr,ha)) {
+ if (!gdth_init_pci(&pcistr[ctr],ha)) {
scsi_unregister(shp);
continue;
}
/* controller found and initialized */
printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
- pcistr.bus,pcistr.device_fn>>3,ha->irq);
+ pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
- save_flags(flags);
- cli();
#if LINUX_VERSION_CODE >= 0x010346
- if (request_irq(ha->irq,do_gdth_interrupt,SA_INTERRUPT,"gdth",NULL))
+ if (request_irq(ha->irq, gdth_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
#else
- if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth"))
+ if (request_irq(ha->irq, gdth_interrupt,
+ SA_INTERRUPT|SA_SHIRQ, "gdth"))
#endif
{
printk("GDT-PCI: Unable to allocate IRQ\n");
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
shp->unchecked_isa_dma = 0;
shp->irq = ha->irq;
shp->dma_channel = 0xff;
- for (i=0; i<MAXID; ++i) {
- if (ha->id[0][i].type==SIOP_DTYP) {
- shp->this_id = i;
- break;
- }
- }
hanum = gdth_ctr_count;
gdth_ctr_tab[gdth_ctr_count++] = shp;
gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
@@ -3009,55 +3405,48 @@ int gdth_detect(Scsi_Host_Template *shtp)
NUMDATA(shp)->busnum= 0;
ha->pccb = CMDDATA(shp);
- ha->pscratch = DMADATA(shp);
+ ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+ ha->scratch_busy = FALSE;
ha->req_first = NULL;
- for (i=0; i<MAXBUS; ++i) {
- for (j=0; j<MAXID; ++j) {
- ha->id[i][j].type = EMPTY_DTYP;
- ha->id[i][j].lock = 0;
- }
- }
- restore_flags(flags);
-
- if (!gdth_search_drives(hanum)) {
+ ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
+ if (max_ids > 0 && max_ids < ha->tid_cnt)
+ ha->tid_cnt = max_ids;
+ for (i=0; i<GDTH_MAXCMDS; ++i)
+ ha->cmd_tab[i].cmnd = UNUSED_CMND;
+ ha->scan_mode = rescan ? 0x10 : 0;
+
+ if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
printk("GDT-PCI: Error during device scan\n");
--gdth_ctr_count;
- --gdth_ctr_vcount;
- save_flags(flags);
- cli();
+ --gdth_ctr_vcount;
+ if (ha->pscratch != NULL)
+ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
#if LINUX_VERSION_CODE >= 0x010346
free_irq(ha->irq,NULL);
#else
free_irq(ha->irq);
#endif
- restore_flags(flags);
scsi_unregister(shp);
continue;
}
#if LINUX_VERSION_CODE >= 0x020000
- shp->max_id = 8;
- shp->max_lun = 8;
- shp->max_channel = ha->bus_cnt - 1;
+ shp->max_id = ha->tid_cnt;
+ shp->max_lun = MAXLUN;
+ shp->max_channel = ha->bus_cnt;
#else
/* register addit. SCSI channels as virtual controllers */
- for (b=1; b<ha->bus_cnt; ++b) {
+ for (b=1; b<ha->bus_cnt+1; ++b) {
shp = scsi_register(shtp,sizeof(gdth_num_str));
shp->unchecked_isa_dma = 0;
shp->irq = ha->irq;
shp->dma_channel = 0xff;
- for (i=0; i<MAXID; ++i) {
- if (ha->id[b][i].type==SIOP_DTYP) {
- shp->this_id = i;
- break;
- }
- }
gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
NUMDATA(shp)->hanum = (ushort)hanum;
NUMDATA(shp)->busnum = b;
}
#endif
-
+ GDTH_INIT_LOCK_HA(ha);
gdth_enable_int(hanum);
}
}
@@ -3065,13 +3454,15 @@ int gdth_detect(Scsi_Host_Template *shtp)
TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
if (gdth_ctr_count > 0) {
#ifdef GDTH_STATISTICS
- TRACE2(("gdth_detect(): Initializing timer !\n"));
- timer_table[GDTH_TIMER].fn = gdth_timeout;
- timer_table[GDTH_TIMER].expires = jiffies + HZ;
- timer_active |= 1<<GDTH_TIMER;
+ TRACE2(("gdth_detect(): Initializing timer !\n"));
+ init_timer(&gdth_timer);
+ gdth_timer.expires = jiffies + HZ;
+ gdth_timer.data = 0L;
+ gdth_timer.function = gdth_timeout;
+ add_timer(&gdth_timer);
#endif
#if LINUX_VERSION_CODE >= 0x020100
- register_reboot_notifier(&gdth_notifier);
+ register_reboot_notifier(&gdth_notifier);
#endif
}
gdth_polling = FALSE;
@@ -3081,13 +3472,15 @@ int gdth_detect(Scsi_Host_Template *shtp)
int gdth_release(struct Scsi_Host *shp)
{
- unsigned long flags;
+ int hanum;
+ gdth_ha_str *ha;
TRACE2(("gdth_release()\n"));
-
- save_flags(flags);
- cli();
if (NUMDATA(shp)->busnum == 0) {
+ hanum = NUMDATA(shp)->hanum;
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ gdth_flush(hanum);
+
if (shp->irq) {
#if LINUX_VERSION_CODE >= 0x010346
free_irq(shp->irq,NULL);
@@ -3098,9 +3491,21 @@ int gdth_release(struct Scsi_Host *shp)
if (shp->dma_channel != 0xff) {
free_dma(shp->dma_channel);
}
+ scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+ gdth_ctr_released++;
+ TRACE2(("gdth_release(): HA %d of %d\n",
+ gdth_ctr_released, gdth_ctr_count));
+
+ if (gdth_ctr_released == gdth_ctr_count) {
+#ifdef GDTH_STATISTICS
+ del_timer(&gdth_timer);
+#endif
+#if LINUX_VERSION_CODE >= 0x020100
+ unregister_reboot_notifier(&gdth_notifier);
+#endif
+ }
}
- restore_flags(flags);
scsi_unregister(shp);
return 0;
}
@@ -3117,102 +3522,40 @@ static const char *gdth_ctr_name(int hanum)
if (ha->type == GDT_EISA) {
switch (ha->stype) {
case GDT3_ID:
- return("GDT3000/3020 (EISA)");
+ return("GDT3000/3020");
case GDT3A_ID:
- return("GDT3000A/3020A/3050A (EISA)");
+ return("GDT3000A/3020A/3050A");
case GDT3B_ID:
- return("GDT3000B/3010A (EISA)");
+ return("GDT3000B/3010A");
}
} else if (ha->type == GDT_ISA) {
- return("GDT2000/2020 (ISA)");
+ return("GDT2000/2020");
} else if (ha->type == GDT_PCI) {
switch (ha->stype) {
case PCI_DEVICE_ID_VORTEX_GDT60x0:
- return("GDT6000/6020/6050 (PCI)");
+ return("GDT6000/6020/6050");
case PCI_DEVICE_ID_VORTEX_GDT6000B:
- return("GDT6000B/6010 (PCI)");
- }
- } else if (ha->type == GDT_PCINEW) {
- switch (ha->stype) {
- case PCI_DEVICE_ID_VORTEX_GDT6x10:
- return("GDT6110/6510 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x20:
- return("GDT6120/6520 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6530:
- return("GDT6530 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6550:
- return("GDT6550 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x17:
- return("GDT6117/6517 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x27:
- return("GDT6127/6527 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6537:
- return("GDT6537 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6557:
- return("GDT6557/6557-ECC (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x15:
- return("GDT6115/6515 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x25:
- return("GDT6125/6525 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6535:
- return("GDT6535 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6555:
- return("GDT6555/6555-ECC (PCI)");
+ return("GDT6000B/6010");
}
- } else if (ha->type == GDT_PCIMPR) {
- switch (ha->stype) {
- case PCI_DEVICE_ID_VORTEX_GDT6x17RP:
- return("GDT6117RP/GDT6517RP (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x27RP:
- return("GDT6127RP/GDT6527RP (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6537RP:
- return("GDT6537RP (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6557RP:
- return("GDT6557RP (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x11RP:
- return("GDT6111RP/GDT6511RP (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x21RP:
- return("GDT6121RP/GDT6521RP (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x17RP1:
- return("GDT6117RP1/GDT6517RP1 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x27RP1:
- return("GDT6127RP1/GDT6527RP1 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6537RP1:
- return("GDT6537RP1 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6557RP1:
- return("GDT6557RP1 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x11RP1:
- return("GDT6111RP1/GDT6511RP1 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x21RP1:
- return("GDT6121RP1/GDT6521RP1 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x17RP2:
- return("GDT6117RP2/GDT6517RP2 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x27RP2:
- return("GDT6127RP2/GDT6527RP2 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6537RP2:
- return("GDT6537RP2 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6557RP2:
- return("GDT6557RP2 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x11RP2:
- return("GDT6111RP2/GDT6511RP2 (PCI)");
- case PCI_DEVICE_ID_VORTEX_GDT6x21RP2:
- return("GDT6121RP2/GDT6521RP2 (PCI)");
- }
- }
+ }
+ /* new controllers (GDT_PCINEW, GDT_PCIMPR, ..) use board_info IOCTL! */
+
return("");
}
const char *gdth_info(struct Scsi_Host *shp)
{
int hanum;
-
+ gdth_ha_str *ha;
+
TRACE2(("gdth_info()\n"));
hanum = NUMDATA(shp)->hanum;
+ ha = HADATA(gdth_ctr_tab[hanum]);
- return (gdth_ctr_name(hanum));
+ return ((const char *)ha->ctr_name);
}
-
+/* old error handling */
int gdth_abort(Scsi_Cmnd *scp)
{
TRACE2(("gdth_abort() reason %d\n",scp->abort_reason));
@@ -3229,6 +3572,32 @@ int gdth_reset(Scsi_Cmnd *scp)
return SCSI_RESET_PUNT;
}
+#if LINUX_VERSION_CODE >= 0x02015F
+/* new error handling */
+int gdth_eh_abort(Scsi_Cmnd *scp)
+{
+ TRACE2(("gdth_eh_abort()\n"));
+ return FAILED;
+}
+
+int gdth_eh_device_reset(Scsi_Cmnd *scp)
+{
+ TRACE2(("gdth_eh_device_reset()\n"));
+ return FAILED;
+}
+
+int gdth_eh_bus_reset(Scsi_Cmnd *scp)
+{
+ TRACE2(("gdth_eh_bus_reset()\n"));
+ return FAILED;
+}
+
+int gdth_eh_host_reset(Scsi_Cmnd *scp)
+{
+ TRACE2(("gdth_eh_host_reset()\n"));
+ return FAILED;
+}
+#endif
#if LINUX_VERSION_CODE >= 0x010300
int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
@@ -3236,18 +3605,36 @@ int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
int gdth_bios_param(Disk *disk,int dev,int *ip)
#endif
{
- unchar b, t;
+ unchar t;
int hanum;
gdth_ha_str *ha;
+ int drv_hds, drv_secs;
hanum = NUMDATA(disk->device->host)->hanum;
- b = disk->device->channel;
t = disk->device->id;
- TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t));
+ TRACE2(("gdth_bios_param() ha %d bus %d target %d\n",
+ hanum, disk->device->channel, t));
ha = HADATA(gdth_ctr_tab[hanum]);
- ip[0] = ha->id[b][t].heads;
- ip[1] = ha->id[b][t].secs;
+ if (ha->hdr[t].heads == 0) {
+ /* raw device: evaluate mapping (sectors per head, heads per cylinder) */
+ if (disk->capacity /HEADS/SECS <= MAXCYLS) {
+ drv_hds = HEADS;
+ drv_secs= SECS;
+ } else if (disk->capacity /MEDHEADS/MEDSECS <= MAXCYLS) {
+ drv_hds = MEDHEADS;
+ drv_secs= MEDSECS;
+ } else {
+ drv_hds = BIGHEADS;
+ drv_secs= BIGSECS;
+ }
+ ha->hdr[t].heads = drv_hds;
+ ha->hdr[t].secs = drv_secs;
+ TRACE2(("gdth_bios_param(): raw device -> params evaluated\n"));
+ }
+
+ ip[0] = ha->hdr[t].heads;
+ ip[1] = ha->hdr[t].secs;
ip[2] = disk->capacity / ip[0] / ip[1];
TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
@@ -3280,10 +3667,12 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
int priority;
TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
- scp->cmnd[0],scp->target,scp->lun));
+ scp->cmnd[0],scp->target,scp->lun));
scp->scsi_done = (void *)done;
- scp->SCp.have_data_in = 0;
+ scp->SCp.have_data_in = 1;
+ scp->SCp.phase = -1;
+ scp->SCp.Status = -1;
hanum = NUMDATA(scp->host)->hanum;
#ifdef GDTH_STATISTICS
++act_ios;
@@ -3299,6 +3688,52 @@ int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
return 0;
}
+/* flush routine */
+static void gdth_flush(int hanum)
+{
+ int i;
+ gdth_ha_str *ha;
+ Scsi_Cmnd scp;
+ Scsi_Device sdev;
+ gdth_cmd_str gdtcmd;
+ char cmnd[12];
+
+ TRACE2(("gdth_flush() hanum %d\n",hanum));
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ memset(&sdev,0,sizeof(Scsi_Device));
+ memset(&scp, 0,sizeof(Scsi_Cmnd));
+ sdev.host = gdth_ctr_tab[hanum];
+ sdev.id = sdev.host->this_id;
+ scp.cmd_len = 12;
+ scp.host = gdth_ctr_tab[hanum];
+ scp.target = sdev.host->this_id;
+ scp.device = &sdev;
+ scp.use_sg = 0;
+
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (ha->hdr[i].present) {
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_FLUSH;
+ gdtcmd.u.cache.DeviceNo = i;
+ gdtcmd.u.cache.BlockNo = 1;
+ gdtcmd.u.cache.sg_canz = 0;
+ TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
+ {
+ struct semaphore sem = MUTEX_LOCKED;
+ scp.request.rq_status = RQ_SCSI_BUSY;
+ scp.request.sem = &sem;
+ scp.SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
+ scsi_do_cmd(&scp, cmnd, &gdtcmd,
+ sizeof(gdth_cmd_str), gdth_scsi_done,
+ 30*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
+ down(&sem);
+ }
+ }
+ }
+}
/* shutdown routine */
#if LINUX_VERSION_CODE >= 0x020100
@@ -3307,23 +3742,32 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
void gdth_halt(void)
#endif
{
- int hanum, i, j;
- gdth_ha_str *ha;
+ int hanum;
+#ifndef __alpha__
Scsi_Cmnd scp;
Scsi_Device sdev;
gdth_cmd_str gdtcmd;
char cmnd[12];
+#endif
#if LINUX_VERSION_CODE >= 0x020100
TRACE2(("gdth_halt() event %d\n",event));
if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
- return NOTIFY_DONE;
+ return NOTIFY_DONE;
#else
TRACE2(("gdth_halt()\n"));
+ if (halt_called) {
+ TRACE2(("already called\n"));
+ return;
+ }
+ halt_called = TRUE;
#endif
printk("GDT: Flushing all host drives .. ");
for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
- ha = HADATA(gdth_ctr_tab[hanum]);
+ gdth_flush(hanum);
+
+#ifndef __alpha__
+ /* controller reset */
memset(&sdev,0,sizeof(Scsi_Device));
memset(&scp, 0,sizeof(Scsi_Cmnd));
sdev.host = gdth_ctr_tab[hanum];
@@ -3334,32 +3778,6 @@ void gdth_halt(void)
scp.device = &sdev;
scp.use_sg = 0;
- /* flush */
- for (i = 0; i < MAXBUS; ++i) {
- for (j = 0; j < MAXID; ++j) {
- if (ha->id[i][j].type == CACHE_DTYP) {
- gdtcmd.BoardNode = LOCALBOARD;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_FLUSH;
- gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive;
- gdtcmd.u.cache.BlockNo = 1;
- gdtcmd.u.cache.sg_canz = 0;
- TRACE2(("gdth_halt(): flush ha %d drive %d\n",
- hanum, ha->id[i][j].hostdrive));
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 30*HZ, 1);
- down(&sem);
- }
- }
- }
- }
-
- /* controller reset */
gdtcmd.BoardNode = LOCALBOARD;
gdtcmd.Service = CACHESERVICE;
gdtcmd.OpCode = GDT_RESET;
@@ -3368,16 +3786,20 @@ void gdth_halt(void)
struct semaphore sem = MUTEX_LOCKED;
scp.request.rq_status = RQ_SCSI_BUSY;
scp.request.sem = &sem;
+ scp.SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
scsi_do_cmd(&scp, cmnd, &gdtcmd,
sizeof(gdth_cmd_str), gdth_scsi_done,
10*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
down(&sem);
}
+#endif
}
printk("Done.\n");
#ifdef GDTH_STATISTICS
- timer_active &= ~(1<<GDTH_TIMER);
+ del_timer(&gdth_timer);
#endif
#if LINUX_VERSION_CODE >= 0x020100
unregister_reboot_notifier(&gdth_notifier);
@@ -3387,35 +3809,69 @@ void gdth_halt(void)
/* called from init/main.c */
-void gdth_setup(char *str,int *ints)
+__initfunc (void gdth_setup(char *str,int *ints))
{
- static size_t setup_idx = 0;
+ int i, argc;
+ char *cur_str, *argv;
+
+ TRACE2(("gdth_setup() str %s ints[0] %d\n",
+ str ? str:"NULL", ints ? ints[0]:0));
+
+ /* read irq[] from ints[] */
+ if (ints) {
+ argc = ints[0];
+ if (argc > 0) {
+ if (argc > MAXHA)
+ argc = MAXHA;
+ for (i = 0; i < argc; ++i)
+ irq[i] = ints[i+1];
+ }
+ }
- TRACE2(("gdth_setup() str %s ints[0] %d ints[1] %d\n",
- str ? str:"NULL", ints[0],
- ints[0] ? ints[1]:0));
+ /* analyse string */
+ argv = str;
+ while (argv && (cur_str = strchr(argv, ':'))) {
+ int val = 0, c = *++cur_str;
+
+ if (c == 'n' || c == 'N')
+ val = 0;
+ else if (c == 'y' || c == 'Y')
+ val = 1;
+ else
+ val = (int)simple_strtoul(cur_str, NULL, 0);
+
+ if (!strncmp(argv, "disable:", 8))
+ disable = val;
+ else if (!strncmp(argv, "reserve_mode:", 13))
+ reserve_mode = val;
+ else if (!strncmp(argv, "reverse_scan:", 13))
+ reverse_scan = val;
+ else if (!strncmp(argv, "max_ids:", 8))
+ max_ids = val;
+ else if (!strncmp(argv, "rescan:", 7))
+ rescan = val;
+ else if (!strncmp(argv, "reserve_list:", 13)) {
+ reserve_list[0] = val;
+ for (i = 1; i < MAX_RES_ARGS; i++) {
+ cur_str = strchr(cur_str, ',');
+ if (!cur_str)
+ break;
+ if (!isdigit((int)*++cur_str)) {
+ --cur_str;
+ break;
+ }
+ reserve_list[i] =
+ (int)simple_strtoul(cur_str, NULL, 0);
+ }
+ if (!cur_str)
+ break;
+ argv = ++cur_str;
+ continue;
+ }
- if (setup_idx >= MAXHA) {
- printk("GDT: gdth_setup() called too many times. Bad LILO params ?\n");
- return;
+ if ((argv = strchr(argv, ',')))
+ ++argv;
}
- if (ints[0] != 1) {
- printk("GDT: Illegal command line !\n");
- printk("Usage: gdth=<IRQ>\n");
- printk("Where: <IRQ>: valid EISA controller IRQ (10,11,12,14)\n");
- printk(" or 0 to disable controller driver\n");
- return;
- }
- if (ints[1] == 10 || ints[1] == 11 || ints[1] == 12 || ints[1] == 14) {
- irqs[setup_idx++] = ints[1];
- irqs[setup_idx] = 0xff;
- return;
- }
- if (ints[1] == 0) {
- disable_gdth_scan = TRUE;
- return;
- }
- printk("GDT: Invalid IRQ (%d) specified\n",ints[1]);
}
@@ -3423,4 +3879,3 @@ void gdth_setup(char *str,int *ints)
Scsi_Host_Template driver_template = GDTH;
#include "scsi_module.c"
#endif
-
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index ad2c3eed0..93db2e540 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -4,13 +4,13 @@
/*
* Header file for the GDT ISA/EISA/PCI Disk Array Controller driver for Linux
*
- * gdth.h Copyright (C) 1995-97 ICP vortex Computersysteme GmbH, Achim Leubner
+ * gdth.h Copyright (C) 1995-98 ICP vortex Computersysteme GmbH, Achim Leubner
* See gdth.c for further informations and
* below for supported controller types
*
* <achim@vortex.de>
*
- * $Id: gdth.h,v 1.9 1997/11/04 09:55:42 achim Exp $
+ * $Id: gdth.h,v 1.16 1998/12/17 15:54:53 achim Exp $
*/
#include <linux/version.h>
@@ -29,9 +29,9 @@
/* defines, macros */
/* driver version */
-#define GDTH_VERSION_STR "1.02"
+#define GDTH_VERSION_STR "1.10"
#define GDTH_VERSION 1
-#define GDTH_SUBVERSION 2
+#define GDTH_SUBVERSION 10
/* protocol version */
#define PROTOCOL_VERSION 1
@@ -48,11 +48,13 @@
#define GDT3B_ID 0x0330941c /* GDT3000B/3010A */
/* GDT_ISA */
#define GDT2_ID 0x0120941c /* GDT2000/2020 */
+
/* vendor ID, device IDs (PCI) */
/* these defines should already exist in <linux/pci.h> */
#ifndef PCI_VENDOR_ID_VORTEX
#define PCI_VENDOR_ID_VORTEX 0x1119 /* PCI controller vendor ID */
#endif
+
#ifndef PCI_DEVICE_ID_VORTEX_GDT60x0
/* GDT_PCI */
#define PCI_DEVICE_ID_VORTEX_GDT60x0 0 /* GDT6000/6020/6050 */
@@ -83,22 +85,44 @@
/* GDT_MPR, RP series, narrow/ultra SCSI */
#define PCI_DEVICE_ID_VORTEX_GDT6x11RP 0x104 /* GDT6111RP/GDT6511RP */
#define PCI_DEVICE_ID_VORTEX_GDT6x21RP 0x105 /* GDT6121RP/GDT6521RP */
-/* GDT_MPR, RP1 series, wide/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP1 0x110 /* GDT6117RP1/GDT6517RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP1 0x111 /* GDT6127RP1/GDT6527RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP1 0x112 /* GDT6537RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP1 0x113 /* GDT6557RP1 */
-/* GDT_MPR, RP1 series, narrow/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP1 0x114 /* GDT6111RP1/GDT6511RP1 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP1 0x115 /* GDT6121RP1/GDT6521RP1 */
-/* GDT_MPR, RP2 series, wide/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x17RP2 0x120 /* GDT6117RP2/GDT6517RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x27RP2 0x121 /* GDT6127RP2/GDT6527RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6537RP2 0x122 /* GDT6537RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6557RP2 0x123 /* GDT6557RP2 */
-/* GDT_MPR, RP2 series, narrow/ultra SCSI */
-#define PCI_DEVICE_ID_VORTEX_GDT6x11RP2 0x124 /* GDT6111RP2/GDT6511RP2 */
-#define PCI_DEVICE_ID_VORTEX_GDT6x21RP2 0x125 /* GDT6121RP2/GDT6521RP2 */
+#endif
+#ifndef PCI_DEVICE_ID_VORTEX_GDT6x17RD
+/* GDT_MPR, RD series, wide/ultra SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT6x17RD 0x110 /* GDT6117RD/GDT6517RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x27RD 0x111 /* GDT6127RD/GDT6527RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6537RD 0x112 /* GDT6537RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6557RD 0x113 /* GDT6557RD */
+/* GDT_MPR, RD series, narrow/ultra SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT6x11RD 0x114 /* GDT6111RD/GDT6511RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x21RD 0x115 /* GDT6121RD/GDT6521RD */
+/* GDT_MPR, RD series, wide/ultra2 SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT6x18RD 0x118 /* GDT6118RD/GDT6518RD/
+ GDT6618RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x28RD 0x119 /* GDT6128RD/GDT6528RD/
+ GDT6628RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x38RD 0x11A /* GDT6538RD/GDT6638RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x58RD 0x11B /* GDT6558RD/GDT6658RD */
+/* GDT_MPR, RN series (64-bit PCI), wide/ultra2 SCSI */
+#define PCI_DEVICE_ID_VORTEX_GDT7x18RN 0x168 /* GDT7118RN/GDT7518RN/
+ GDT7618RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x28RN 0x169 /* GDT7128RN/GDT7528RN/
+ GDT7628RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x38RN 0x16A /* GDT7538RN/GDT7638RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x58RN 0x16B /* GDT7558RN/GDT7658RN */
+#endif
+
+#ifndef PCI_DEVICE_ID_VORTEX_GDT6x19RD
+/* GDT_MPR, RD series, Fibre Channel */
+#define PCI_DEVICE_ID_VORTEX_GDT6x19RD 0x210 /* GDT6519RD/GDT6619RD */
+#define PCI_DEVICE_ID_VORTEX_GDT6x29RD 0x211 /* GDT6529RD/GDT6629RD */
+/* GDT_MPR, RN series (64-bit PCI), Fibre Channel */
+#define PCI_DEVICE_ID_VORTEX_GDT7x19RN 0x260 /* GDT7519RN/GDT7619RN */
+#define PCI_DEVICE_ID_VORTEX_GDT7x29RN 0x261 /* GDT7529RN/GDT7629RN */
+#endif
+
+#ifndef PCI_DEVICE_ID_VORTEX_GDTMAXRP
+/* GDT_MPR, last device ID */
+#define PCI_DEVICE_ID_VORTEX_GDTMAXRP 0x2ff
#endif
/* limits */
@@ -106,12 +130,14 @@
#define GDTH_MAXCMDS 124
#define GDTH_MAXC_P_L 16 /* max. cmds per lun */
#define MAXOFFSETS 128
-#define MAXHA 8
-#define MAXID 8
+#define MAXHA 16
+#define MAXID 127
#define MAXLUN 8
-#define MAXBUS 5
+#define MAXBUS 6
#define MAX_HDRIVES 35 /* max. host drive count */
#define MAX_EVENTS 100 /* event buffer count */
+#define MAX_RES_ARGS 40 /* device reservation,
+ must be a multiple of 4 */
#define MAXCYLS 1024
#define HEADS 64
#define SECS 32 /* mapping 64*32 */
@@ -126,12 +152,6 @@
#define SCREEN_CMND ((Scsi_Cmnd *)-3)
#define SPECIAL_SCP(p) (p==UNUSED_CMND || p==INTERNAL_CMND || p==SCREEN_CMND)
-/* device types */
-#define EMPTY_DTYP 0
-#define CACHE_DTYP 1
-#define RAW_DTYP 2
-#define SIOP_DTYP 3 /* the SCSI processor */
-
/* controller services */
#define SCSIRAWSERVICE 3
#define CACHESERVICE 9
@@ -144,14 +164,15 @@
#define MSG_REQUEST 0 /* async. event: message */
/* cacheservice defines */
-#define SECTOR_SIZE 0x200 /* always 512 bytes per sector */
+#define SECTOR_SIZE 0x200 /* always 512 bytes per sec. */
/* DPMEM constants */
+#define DPMEM_MAGIC 0xC0FFEE11
#define IC_HEADER_BYTES 48
#define IC_QUEUE_BYTES 4
#define DPMEM_COMMAND_OFFSET IC_HEADER_BYTES+IC_QUEUE_BYTES*MAXOFFSETS
-/* service commands */
+/* cache/raw service commands */
#define GDT_INIT 0 /* service initialization */
#define GDT_READ 1 /* read command */
#define GDT_WRITE 2 /* write command */
@@ -163,16 +184,27 @@
#define GDT_UNMOUNT 11 /* unmount cache device */
#define GDT_SET_FEAT 12 /* set feat. (scatter/gather) */
#define GDT_GET_FEAT 13 /* get features */
-#define GDT_RESERVE 14 /* reserve dev. to raw service */
#define GDT_WRITE_THR 16 /* write through */
+#define GDT_READ_THR 17 /* read through */
#define GDT_EXT_INFO 18 /* extended info */
#define GDT_RESET 19 /* controller reset */
+/* additional raw service commands */
+#define GDT_RESERVE 14 /* reserve dev. to raw serv. */
+#define GDT_RELEASE 15 /* release device */
+#define GDT_RESERVE_ALL 16 /* reserve all devices */
+#define GDT_RELEASE_ALL 17 /* release all devices */
+#define GDT_RESET_BUS 18 /* reset bus */
+#define GDT_SCAN_START 19 /* start device scan */
+#define GDT_SCAN_END 20 /* stop device scan */
+
/* IOCTL command defines */
#define SCSI_CHAN_CNT 5 /* subfunctions */
+#define GET_IOCHAN_DESC 0x5e
#define L_CTRL_PATTERN 0x20000000L
#define CACHE_INFO 4
#define CACHE_CONFIG 5
+#define BOARD_INFO 0x28
#define IO_CHANNEL 0x00020000L /* channels */
#define INVALID_CHANNEL 0x0000ffffL
@@ -200,6 +232,7 @@
/* priorities */
#define DEFAULT_PRI 0x20
#define IOCTL_PRI 0x10
+#define HIGH_PRI 0x08
/* data directions */
#define DATA_IN 0x01000000L /* data from target */
@@ -211,7 +244,7 @@
#define SEMA0REG 0x0c8a /* command semaphore */
#define SEMA1REG 0x0c8b /* status semaphore */
#define LDOORREG 0x0c8d /* local doorbell */
-#define EDENABREG 0x0c8e /* EISA system doorbell enable */
+#define EDENABREG 0x0c8e /* EISA system doorbell enab. */
#define EDOORREG 0x0c8f /* EISA system doorbell */
#define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */
#define EISAREG 0x0cc0 /* EISA configuration */
@@ -221,119 +254,160 @@
#define SCATTER_GATHER 1 /* s/g feature */
#define GDTH_MAXSG 32 /* max. s/g elements */
#define SECS32 0x1f /* round capacity */
-#define BIOS_ID_OFFS 0x10 /* offset contr. ID in ISABIOS */
+#define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */
#define LOCALBOARD 0 /* board node always 0 */
#define ASYNCINDEX 0 /* cmd index async. event */
#define SPEZINDEX 1 /* cmd index unknown service */
#define GDT_WR_THROUGH 0x100 /* WRITE_THROUGH supported */
-/* typedefs */
-
-#pragma pack(1)
-typedef struct {
- char buffer[GDTH_SCRATCH]; /* scratch buffer */
-} gdth_scratch_str;
+/* typedefs */
+typedef u32 ulong32;
+#define PACKED __attribute__((packed))
/* screenservice message */
typedef struct {
- ulong msg_handle; /* message handle */
- ulong msg_len; /* size of message */
- ulong msg_alen; /* answer length */
+ ulong32 msg_handle; /* message handle */
+ ulong32 msg_len; /* size of message */
+ ulong32 msg_alen; /* answer length */
unchar msg_answer; /* answer flag */
unchar msg_ext; /* more messages */
unchar msg_reserved[2];
char msg_text[MSGLEN+2]; /* the message text */
-} gdth_msg_str;
+} PACKED gdth_msg_str;
/* get channel count IOCTL */
typedef struct {
- ulong channel_no; /* number of channel */
- ulong drive_cnt; /* number of drives */
+ ulong32 channel_no; /* number of channel */
+ ulong32 drive_cnt; /* number of drives */
unchar siop_id; /* SCSI processor ID */
unchar siop_state; /* SCSI processor state */
-} gdth_getch_str;
+} PACKED gdth_getch_str;
+
+/* get raw channel count IOCTL (NEW!) */
+typedef struct {
+ ulong32 version; /* version of information (-1UL: newest) */
+ unchar list_entries; /* list entry count */
+ unchar first_chan; /* first channel number */
+ unchar last_chan; /* last channel number */
+ unchar chan_count; /* (R) channel count */
+ ulong32 list_offset; /* offset of list[0] */
+ struct {
+ unchar proc_id; /* processor id */
+ unchar proc_defect; /* defect ? */
+ unchar reserved[2];
+ } PACKED list[MAXBUS];
+} PACKED gdth_iochan_str;
/* cache info/config IOCTL */
typedef struct {
- ulong version; /* firmware version */
+ ulong32 version; /* firmware version */
ushort state; /* cache state (on/off) */
ushort strategy; /* cache strategy */
ushort write_back; /* write back state (on/off) */
ushort block_size; /* cache block size */
-} gdth_cpar_str;
+} PACKED gdth_cpar_str;
typedef struct {
- ulong csize; /* cache size */
- ulong read_cnt; /* read/write counter */
- ulong write_cnt;
- ulong tr_hits; /* hits */
- ulong sec_hits;
- ulong sec_miss; /* misses */
-} gdth_cstat_str;
+ ulong32 csize; /* cache size */
+ ulong32 read_cnt; /* read/write counter */
+ ulong32 write_cnt;
+ ulong32 tr_hits; /* hits */
+ ulong32 sec_hits;
+ ulong32 sec_miss; /* misses */
+} PACKED gdth_cstat_str;
typedef struct {
gdth_cpar_str cpar;
gdth_cstat_str cstat;
-} gdth_cinfo_str;
+} PACKED gdth_cinfo_str;
+
+/* board info IOCTL */
+typedef struct {
+ ulong32 ser_no; /* serial no. */
+ unchar oem_id[2]; /* OEM ID */
+ ushort ep_flags; /* eprom flags */
+ ulong32 proc_id; /* processor ID */
+ ulong32 memsize; /* memory size (bytes) */
+ unchar mem_banks; /* memory banks */
+ unchar chan_type; /* channel type */
+ unchar chan_count; /* channel count */
+ unchar rdongle_pres; /* dongle present? */
+ ulong32 epr_fw_ver; /* (eprom) firmware version */
+ ulong32 upd_fw_ver; /* (update) firmware version */
+ ulong32 upd_revision; /* update revision */
+ char type_string[16]; /* controller name */
+ char raid_string[16]; /* RAID firmware name */
+ unchar update_pres; /* update present? */
+ unchar xor_pres; /* XOR engine present? */
+ unchar prom_type; /* ROM type (eprom/flash) */
+ unchar prom_count; /* number of ROM devices */
+ ulong32 dup_pres; /* duplexing module present? */
+ ulong32 chan_pres; /* number of expansion chn. */
+ ulong32 mem_pres; /* memory expansion inst. ? */
+ unchar ft_bus_system; /* fault bus supported? */
+ unchar subtype_valid; /* board_subtype valid? */
+ unchar board_subtype; /* subtype/hardware level */
+ unchar ramparity_pres; /* RAM parity check hardware? */
+} PACKED gdth_binfo_str;
/* scatter/gather element */
typedef struct {
- ulong sg_ptr; /* address */
- ulong sg_len; /* length */
-} gdth_sg_str;
+ ulong32 sg_ptr; /* address */
+ ulong32 sg_len; /* length */
+} PACKED gdth_sg_str;
/* command structure */
typedef struct {
- ulong BoardNode; /* board node (always 0) */
- ulong CommandIndex; /* command number */
+ ulong32 BoardNode; /* board node (always 0) */
+ ulong32 CommandIndex; /* command number */
ushort OpCode; /* the command (READ,..) */
union {
struct {
ushort DeviceNo; /* number of cache drive */
- ulong BlockNo; /* block number */
- ulong BlockCnt; /* block count */
- ulong DestAddr; /* dest. addr. (if s/g: -1) */
- ulong sg_canz; /* s/g element count */
+ ulong32 BlockNo; /* block number */
+ ulong32 BlockCnt; /* block count */
+ ulong32 DestAddr; /* dest. addr. (if s/g: -1) */
+ ulong32 sg_canz; /* s/g element count */
gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */
- } cache; /* cache service cmd. str. */
+ } PACKED cache; /* cache service cmd. str. */
struct {
ushort param_size; /* size of p_param buffer */
- ulong subfunc; /* IOCTL function */
- ulong channel; /* device */
- ulong p_param; /* buffer */
- } ioctl; /* IOCTL command structure */
+ ulong32 subfunc; /* IOCTL function */
+ ulong32 channel; /* device */
+ ulong32 p_param; /* buffer */
+ } PACKED ioctl; /* IOCTL command structure */
struct {
ushort reserved;
- ulong msg_handle; /* message handle */
- ulong msg_addr; /* message buffer address */
- } screen; /* screen service cmd. str. */
+ ulong32 msg_handle; /* message handle */
+ ulong32 msg_addr; /* message buffer address */
+ } PACKED screen; /* screen service cmd. str. */
struct {
ushort reserved;
- ulong direction; /* data direction */
- ulong mdisc_time; /* disc. time (0: no timeout)*/
- ulong mcon_time; /* connect time(0: no to.) */
- ulong sdata; /* dest. addr. (if s/g: -1) */
- ulong sdlen; /* data length (bytes) */
- ulong clen; /* SCSI cmd. length(6,10,12) */
+ ulong32 direction; /* data direction */
+ ulong32 mdisc_time; /* disc. time (0: no timeout)*/
+ ulong32 mcon_time; /* connect time(0: no to.) */
+ ulong32 sdata; /* dest. addr. (if s/g: -1) */
+ ulong32 sdlen; /* data length (bytes) */
+ ulong32 clen; /* SCSI cmd. length(6,10,12) */
unchar cmd[12]; /* SCSI command */
unchar target; /* target ID */
unchar lun; /* LUN */
unchar bus; /* SCSI bus number */
unchar priority; /* only 0 used */
- ulong sense_len; /* sense data length */
- ulong sense_data; /* sense data addr. */
+ ulong32 sense_len; /* sense data length */
+ ulong32 sense_data; /* sense data addr. */
struct raw *link_p; /* linked cmds (not supp.) */
- ulong sg_ranz; /* s/g element count */
+ ulong32 sg_ranz; /* s/g element count */
gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */
- } raw; /* raw service cmd. struct. */
+ } PACKED raw; /* raw service cmd. struct. */
} u;
/* additional variables */
unchar Service; /* controller service */
ushort Status; /* command result */
- ulong Info; /* additional information */
+ ulong32 Info; /* additional information */
Scsi_Cmnd *RequestBuffer; /* request buffer */
-} gdth_cmd_str;
+} PACKED gdth_cmd_str;
/* controller event structure */
#define ES_ASYNC 1
@@ -347,40 +421,40 @@ typedef struct {
struct {
ushort ionode;
ushort service;
- ulong index;
- } driver;
+ ulong32 index;
+ } PACKED driver;
struct {
ushort ionode;
ushort service;
ushort status;
- ulong info;
+ ulong32 info;
unchar scsi_coord[3];
- } async;
+ } PACKED async;
struct {
ushort ionode;
ushort service;
ushort status;
- ulong info;
+ ulong32 info;
ushort hostdrive;
unchar scsi_coord[3];
unchar sense_key;
- } sync;
+ } PACKED sync;
struct {
- ulong l1, l2, l3, l4;
- } test;
+ ulong32 l1, l2, l3, l4;
+ } PACKED test;
} eu;
-} gdth_evt_data;
+} PACKED gdth_evt_data;
typedef struct {
- ulong first_stamp;
- ulong last_stamp;
+ ulong32 first_stamp;
+ ulong32 last_stamp;
ushort same_count;
ushort event_source;
ushort event_idx;
unchar application;
unchar reserved;
gdth_evt_data event_data;
-} gdth_evt_str;
+} PACKED gdth_evt_str;
/* DPRAM structures */
@@ -390,32 +464,32 @@ typedef struct {
unchar S_Cmd_Indx; /* special command */
unchar volatile S_Status; /* status special command */
ushort reserved1;
- ulong S_Info[4]; /* add. info special command */
+ ulong32 S_Info[4]; /* add. info special command */
unchar volatile Sema0; /* command semaphore */
unchar reserved2[3];
unchar Cmd_Index; /* command number */
unchar reserved3[3];
ushort volatile Status; /* command status */
ushort Service; /* service(for async.events) */
- ulong Info[2]; /* additional info */
+ ulong32 Info[2]; /* additional info */
struct {
ushort offset; /* command offs. in the DPRAM*/
ushort serv_id; /* service */
- } comm_queue[MAXOFFSETS]; /* command queue */
- ulong bios_reserved[2];
+ } PACKED comm_queue[MAXOFFSETS]; /* command queue */
+ ulong32 bios_reserved[2];
unchar gdt_dpr_cmd[1]; /* commands */
-} gdt_dpr_if;
+} PACKED gdt_dpr_if;
/* SRAM structure PCI controllers */
typedef struct {
- ulong magic; /* controller ID from BIOS */
+ ulong32 magic; /* controller ID from BIOS */
ushort need_deinit; /* switch betw. BIOS/driver */
unchar switch_support; /* see need_deinit */
unchar padding[9];
unchar os_used[16]; /* OS code per service */
unchar unused[28];
unchar fw_magic; /* contr. ID from firmware */
-} gdt_pci_sram;
+} PACKED gdt_pci_sram;
/* SRAM structure EISA controllers (but NOT GDT3000/3020) */
typedef struct {
@@ -423,7 +497,7 @@ typedef struct {
ushort need_deinit; /* switch betw. BIOS/driver */
unchar switch_support; /* see need_deinit */
unchar padding;
-} gdt_eisa_sram;
+} PACKED gdt_eisa_sram;
/* DPRAM ISA controllers */
@@ -431,12 +505,12 @@ typedef struct {
union {
struct {
unchar bios_used[0x3c00-32]; /* 15KB - 32Bytes BIOS */
- ulong magic; /* controller (EISA) ID */
+ ulong32 magic; /* controller (EISA) ID */
ushort need_deinit; /* switch betw. BIOS/driver */
unchar switch_support; /* see need_deinit */
unchar padding[9];
unchar os_used[16]; /* OS code per service */
- } dp_sram;
+ } PACKED dp_sram;
unchar bios_area[0x4000]; /* 16KB reserved for BIOS */
} bu;
union {
@@ -450,8 +524,8 @@ typedef struct {
unchar irqdel; /* acknowledge board int. */
unchar volatile Sema1; /* status semaphore */
unchar rq; /* IRQ/DRQ configuration */
- } io;
-} gdt2_dpram_str;
+ } PACKED io;
+} PACKED gdt2_dpram_str;
/* DPRAM PCI controllers */
typedef struct {
@@ -470,8 +544,8 @@ typedef struct {
unchar unused3[3];
unchar irqdel; /* acknowledge board int. */
unchar unused4[3];
- } io;
-} gdt6_dpram_str;
+ } PACKED io;
+} PACKED gdt6_dpram_str;
/* PLX register structure (new PCI controllers) */
typedef struct {
@@ -482,7 +556,7 @@ typedef struct {
unchar unused2[2];
ushort volatile status; /* command status */
ushort service; /* service */
- ulong info[2]; /* additional info */
+ ulong32 info[2]; /* additional info */
unchar unused3[0x10];
unchar ldoor_reg; /* PCI to local doorbell */
unchar unused4[3];
@@ -491,7 +565,7 @@ typedef struct {
unchar control0; /* control0 register(unused) */
unchar control1; /* board interrupts enable */
unchar unused6[0x16];
-} gdt6c_plx_regs;
+} PACKED gdt6c_plx_regs;
/* DPRAM new PCI controllers */
typedef struct {
@@ -500,7 +574,7 @@ typedef struct {
unchar if_area[0x4000-sizeof(gdt_pci_sram)];
} u;
gdt_pci_sram gdt6sr; /* SRAM structure */
-} gdt6c_dpram_str;
+} PACKED gdt6c_dpram_str;
/* i960 register structure (PCI MPR controllers) */
typedef struct {
@@ -511,15 +585,15 @@ typedef struct {
unchar unused3;
ushort volatile status; /* command status */
ushort service; /* service */
- ulong info[2]; /* additional info */
+ ulong32 info[2]; /* additional info */
unchar ldoor_reg; /* PCI to local doorbell */
unchar unused4[11];
unchar volatile edoor_reg; /* local to PCI doorbell */
unchar unused5[7];
unchar edoor_en_reg; /* board interrupts enable */
unchar unused6[27];
- ulong unused7[1004]; /* size: 4 KB */
-} gdt6m_i960_regs;
+ ulong32 unused7[1004]; /* size: 4 KB */
+} PACKED gdt6m_i960_regs;
/* DPRAM PCI MPR controllers */
typedef struct {
@@ -529,58 +603,71 @@ typedef struct {
unchar if_area[0x3000-sizeof(gdt_pci_sram)];
} u;
gdt_pci_sram gdt6sr; /* SRAM structure */
-} gdt6m_dpram_str;
+} PACKED gdt6m_dpram_str;
/* PCI resources */
typedef struct {
- ushort device_id; /* device ID (0,..,9) */
- unchar bus; /* PCI bus */
- unchar device_fn; /* PCI device/function no. */
- ulong dpmem; /* DPRAM address */
- ulong io; /* IO address */
- ulong io_mm; /* IO address mem. mapped */
- ulong bios; /* BIOS address */
- unchar irq; /* IRQ */
+#if LINUX_VERSION_CODE >= 0x02015C
+ struct pci_dev *pdev;
+#endif
+ ushort device_id; /* device ID (0,..,9) */
+ unchar bus; /* PCI bus */
+ unchar device_fn; /* PCI device/function no. */
+ ulong dpmem; /* DPRAM address */
+ ulong io; /* IO address */
+ ulong io_mm; /* IO address mem. mapped */
+ unchar irq; /* IRQ */
} gdth_pci_str;
/* controller information structure */
typedef struct {
- unchar bus_cnt; /* SCSI bus count */
- unchar type; /* controller class */
+ ushort type; /* controller class */
ushort raw_feat; /* feat. raw service (s/g,..) */
- ulong stype; /* controller subtype */
+ ulong32 stype; /* controller subtype */
ushort cache_feat; /* feat. cache serv. (s/g,..) */
- ushort bmic; /* BMIC address (EISA) */
- void *brd; /* DPRAM address */
- ulong brd_phys; /* slot number/BIOS address */
+ ushort bmic; /* BMIC address (EISA) */
+ void *brd; /* DPRAM address */
+ ulong32 brd_phys; /* slot number/BIOS address */
gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */
gdth_cmd_str *pccb; /* address command structure */
- gdth_scratch_str *pscratch;
+ char *pscratch; /* scratch (DMA) buffer */
+ unchar scratch_busy; /* in use? */
+ unchar scan_mode; /* current scan mode */
unchar irq; /* IRQ */
unchar drq; /* DRQ (ISA controllers) */
ushort status; /* command status */
- ulong info;
- ulong info2; /* additional info */
+ ulong32 info;
+ ulong32 info2; /* additional info */
Scsi_Cmnd *req_first; /* top of request queue */
struct {
- unchar type; /* device type */
+ unchar present; /* host drive present? */
+ unchar lock; /* drive locked? (hot plug) */
unchar heads; /* mapping */
unchar secs;
- unchar lock; /* drive locked ? (hot plug) */
- ushort hostdrive; /* host drive number */
ushort devtype; /* further information */
- ulong size; /* capacity */
- } id[MAXBUS][MAXID];
+ ulong32 size; /* capacity */
+ } hdr[MAXID]; /* host drives */
+ struct {
+ unchar lock; /* channel locked? (hot plug) */
+ } raw[MAXBUS]; /* raw devices */
+ struct {
+ Scsi_Cmnd *cmnd; /* pending request */
+ ushort service; /* service */
+ } cmd_tab[GDTH_MAXCMDS]; /* table of pend. requests */
+ unchar bus_cnt; /* SCSI bus count */
+ unchar tid_cnt; /* Target ID count */
+ unchar bus_id[MAXBUS]; /* IOP IDs */
ushort cmd_cnt; /* command count in DPRAM */
ushort cmd_len; /* length of actual command */
ushort cmd_offs_dpmem; /* actual offset in DPRAM */
ushort ic_all_size; /* sizeof DPRAM interf. area */
- unchar reserved;
- unchar mode; /* information from /proc */
- ushort param_size;
gdth_cpar_str cpar; /* controller cache par. */
+ char ctr_name[16]; /* controller name */
+#if LINUX_VERSION_CODE >= 0x02015F
+ spinlock_t smp_lock;
+#endif
} gdth_ha_str;
/* structure for scsi_register(), SCSI bus != 0 */
@@ -594,7 +681,6 @@ typedef struct {
gdth_num_str numext; /* must be the first element */
gdth_ha_str haext;
gdth_cmd_str cmdext;
- gdth_scratch_str dmaext;
} gdth_ext_str;
@@ -611,27 +697,27 @@ typedef struct {
unchar vendor[8];
unchar product[16];
unchar revision[4];
-} gdth_inq_data;
+} PACKED gdth_inq_data;
/* READ_CAPACITY data format */
typedef struct {
- ulong last_block_no;
- ulong block_length;
-} gdth_rdcap_data;
+ ulong32 last_block_no;
+ ulong32 block_length;
+} PACKED gdth_rdcap_data;
/* REQUEST_SENSE data format */
typedef struct {
unchar errorcode;
unchar segno;
unchar key;
- ulong info;
+ ulong32 info;
unchar add_length;
- ulong cmd_info;
+ ulong32 cmd_info;
unchar adsc;
unchar adsq;
unchar fruc;
unchar key_spec[3];
-} gdth_sense_data;
+} PACKED gdth_sense_data;
/* MODE_SENSE data format */
typedef struct {
@@ -640,20 +726,20 @@ typedef struct {
unchar med_type;
unchar dev_par;
unchar bd_length;
- } hd;
+ } PACKED hd;
struct {
unchar dens_code;
unchar block_count[3];
unchar reserved;
unchar block_length[3];
- } bd;
-} gdth_modep_data;
+ } PACKED bd;
+} PACKED gdth_modep_data;
+/* stack frame */
typedef struct {
- ulong b[10]; /* 32 bit compiler ! */
-} gdth_stackframe;
+ ulong b[10]; /* 32/64 bit compiler ! */
+} PACKED gdth_stackframe;
-#pragma pack()
/* function prototyping */
@@ -669,27 +755,82 @@ int gdth_reset(Scsi_Cmnd *);
#endif
const char *gdth_info(struct Scsi_Host *);
-
+#if LINUX_VERSION_CODE >= 0x02015F
int gdth_bios_param(Disk *,kdev_t,int *);
extern struct proc_dir_entry proc_scsi_gdth;
int gdth_proc_info(char *,char **,off_t,int,int,int);
-#define GDTH { proc_dir: &proc_scsi_gdth, \
- proc_info: gdth_proc_info, \
- name: "GDT SCSI Disk Array Controller", \
- detect: gdth_detect, \
- release: gdth_release, \
- info: gdth_info, \
- command: gdth_command, \
- queuecommand: gdth_queuecommand, \
- abort: gdth_abort, \
- reset: gdth_reset, \
- bios_param: gdth_bios_param, \
- can_queue: GDTH_MAXCMDS, \
- this_id: -1, \
- sg_tablesize: GDTH_MAXSG, \
- cmd_per_lun: GDTH_MAXC_P_L, \
- unchecked_isa_dma: 1, \
- use_clustering: ENABLE_CLUSTERING}
+int gdth_eh_abort(Scsi_Cmnd *scp);
+int gdth_eh_device_reset(Scsi_Cmnd *scp);
+int gdth_eh_bus_reset(Scsi_Cmnd *scp);
+int gdth_eh_host_reset(Scsi_Cmnd *scp);
+#define GDTH { proc_dir: &proc_scsi_gdth, \
+ proc_info: gdth_proc_info, \
+ name: "GDT SCSI Disk Array Controller",\
+ detect: gdth_detect, \
+ release: gdth_release, \
+ info: gdth_info, \
+ command: gdth_command, \
+ queuecommand: gdth_queuecommand, \
+ eh_abort_handler: gdth_eh_abort, \
+ eh_device_reset_handler: gdth_eh_device_reset, \
+ eh_bus_reset_handler: gdth_eh_bus_reset, \
+ eh_host_reset_handler: gdth_eh_host_reset, \
+ abort: gdth_abort, \
+ reset: gdth_reset, \
+ bios_param: gdth_bios_param, \
+ can_queue: GDTH_MAXCMDS, \
+ this_id: -1, \
+ sg_tablesize: GDTH_MAXSG, \
+ cmd_per_lun: GDTH_MAXC_P_L, \
+ present: 0, \
+ unchecked_isa_dma: 1, \
+ use_clustering: ENABLE_CLUSTERING, \
+ use_new_eh_code: 1 /* use new error code */ }
+#elif LINUX_VERSION_CODE >= 0x010300
+int gdth_bios_param(Disk *,kdev_t,int *);
+extern struct proc_dir_entry proc_scsi_gdth;
+int gdth_proc_info(char *,char **,off_t,int,int,int);
+#define GDTH { NULL, NULL, \
+ &proc_scsi_gdth, \
+ gdth_proc_info, \
+ "GDT SCSI Disk Array Controller", \
+ gdth_detect, \
+ gdth_release, \
+ gdth_info, \
+ gdth_command, \
+ gdth_queuecommand, \
+ gdth_abort, \
+ gdth_reset, \
+ NULL, \
+ gdth_bios_param, \
+ GDTH_MAXCMDS, \
+ -1, \
+ GDTH_MAXSG, \
+ GDTH_MAXC_P_L, \
+ 0, \
+ 1, \
+ ENABLE_CLUSTERING}
+#else
+int gdth_bios_param(Disk *,int,int *);
+#define GDTH { NULL, NULL, \
+ "GDT SCSI Disk Array Controller", \
+ gdth_detect, \
+ gdth_release, \
+ gdth_info, \
+ gdth_command, \
+ gdth_queuecommand, \
+ gdth_abort, \
+ gdth_reset, \
+ NULL, \
+ gdth_bios_param, \
+ GDTH_MAXCMDS, \
+ -1, \
+ GDTH_MAXSG, \
+ GDTH_MAXC_P_L, \
+ 0, \
+ 1, \
+ ENABLE_CLUSTERING}
+#endif
#endif
diff --git a/drivers/scsi/gdth_ioctl.h b/drivers/scsi/gdth_ioctl.h
index 01f5db4c5..683956160 100644
--- a/drivers/scsi/gdth_ioctl.h
+++ b/drivers/scsi/gdth_ioctl.h
@@ -2,7 +2,7 @@
#define _GDTH_IOCTL_H
/* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.1 1997/02/21 08:07:27 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.2 1998/12/17 15:42:49 achim Exp $
*/
/* IOCTLs */
@@ -16,12 +16,12 @@
#define GDTIOCTL_LOCKCHN (GDTIOCTL_MASK | 7) /* lock channel */
#define GDTIOCTL_EVENT (GDTIOCTL_MASK | 8) /* read controller events */
-#define GDTIOCTL_MAGIC 0x06030f07UL
+#define GDTIOCTL_MAGIC 0xaffe0001UL
/* IOCTL structure (write) */
typedef struct {
- ulong magic; /* IOCTL magic */
+ ulong32 magic; /* IOCTL magic */
ushort ioctl; /* IOCTL */
ushort ionode; /* controller number */
ushort service; /* controller service */
@@ -43,14 +43,15 @@ typedef struct {
struct {
int erase; /* erase event ? */
int handle;
+ unchar evt[34]; /* event structure */
} event;
} iu;
} gdth_iowr_str;
/* IOCTL structure (read) */
typedef struct {
- ulong size; /* buffer size */
- ulong status; /* IOCTL error code */
+ ulong32 size; /* buffer size */
+ ulong32 status; /* IOCTL error code */
union {
struct {
unchar data[1]; /* data */
@@ -76,7 +77,7 @@ typedef struct {
} ctrcnt;
struct {
int handle;
- unchar evt[32]; /* event structure */
+ unchar evt[34]; /* event structure */
} event;
} iu;
} gdth_iord_str;
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 3fd6968b3..b75bb51cc 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -1,5 +1,5 @@
/* gdth_proc.c
- * $Id: gdth_proc.c,v 1.6 1997/10/31 10:36:24 achim Exp $
+ * $Id: gdth_proc.c,v 1.11 1998/12/17 15:52:35 achim Exp $
*/
#include "gdth_ioctl.h"
@@ -10,7 +10,7 @@ int gdth_proc_info(char *buffer,char **start,off_t offset,int length,
int hanum,busnum,i;
TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n",
- length,hostno,offset,inout));
+ length,hostno,(int)offset,inout));
for (i=0; i<gdth_ctr_vcount; ++i) {
if (gdth_ctr_vtab[i]->host_no == hostno)
@@ -69,7 +69,7 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
{
int orig_length, drive, wb_mode;
char cmnd[12];
- int i, j, found;
+ int i, found;
gdth_ha_str *ha;
gdth_cmd_str gdtcmd;
gdth_cpar_str *pcpar;
@@ -96,28 +96,28 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
} else {
printk("GDT: Flushing all host drives .. ");
}
- for (i = 0; i < MAXBUS; ++i) {
- for (j = 0; j < MAXID; ++j) {
- if (ha->id[i][j].type == CACHE_DTYP) {
- if (drive != -1 &&
- ha->id[i][j].hostdrive != (ushort)drive)
- continue;
- found = TRUE;
- gdtcmd.BoardNode = LOCALBOARD;
- gdtcmd.Service = CACHESERVICE;
- gdtcmd.OpCode = GDT_FLUSH;
- gdtcmd.u.cache.DeviceNo = ha->id[i][j].hostdrive;
- gdtcmd.u.cache.BlockNo = 1;
- gdtcmd.u.cache.sg_canz = 0;
- {
- struct semaphore sem = MUTEX_LOCKED;
- scp.request.rq_status = RQ_SCSI_BUSY;
- scp.request.sem = &sem;
- scsi_do_cmd(&scp, cmnd, &gdtcmd,
- sizeof(gdth_cmd_str), gdth_scsi_done,
- 30*HZ, 1);
- down(&sem);
- }
+ for (i = 0; i < MAX_HDRIVES; ++i) {
+ if (ha->hdr[i].present) {
+ if (drive != -1 && i != drive)
+ continue;
+ found = TRUE;
+ gdtcmd.BoardNode = LOCALBOARD;
+ gdtcmd.Service = CACHESERVICE;
+ gdtcmd.OpCode = GDT_FLUSH;
+ gdtcmd.u.cache.DeviceNo = i;
+ gdtcmd.u.cache.BlockNo = 1;
+ gdtcmd.u.cache.sg_canz = 0;
+ {
+ struct semaphore sem = MUTEX_LOCKED;
+ scp.request.rq_status = RQ_SCSI_BUSY;
+ scp.request.sem = &sem;
+ scp.SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
+ scsi_do_cmd(&scp, cmnd, &gdtcmd,
+ sizeof(gdth_cmd_str), gdth_scsi_done,
+ 30*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
+ down(&sem);
}
}
}
@@ -179,8 +179,11 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
struct semaphore sem = MUTEX_LOCKED;
scp.request.rq_status = RQ_SCSI_BUSY;
scp.request.sem = &sem;
+ scp.SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
scsi_do_cmd(&scp, cmnd, &gdtcmd, sizeof(gdth_cmd_str),
gdth_scsi_done, 30*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
down(&sem);
}
kfree( pcpar );
@@ -195,15 +198,13 @@ static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
{
char cmnd[12];
- int id;
- unchar i, j, k, found;
+ unchar i, j;
gdth_ha_str *ha;
gdth_iowr_str *piowr;
gdth_iord_str *piord;
gdth_cmd_str *pcmd;
- ulong *ppadd;
- ulong add_size, flags;
-
+ ulong32 *ppadd, add_size;
+ ulong flags;
TRACE2(("gdth_set_bin_info() ha %d\n",hanum));
ha = HADATA(gdth_ctr_tab[hanum]);
@@ -228,7 +229,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE;
if (ha->cache_feat & SCATTER_GATHER) {
ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr;
- pcmd->u.cache.DestAddr = -1UL;
+ pcmd->u.cache.DestAddr = 0xffffffff;
pcmd->u.cache.sg_lst[0].sg_len = add_size;
pcmd->u.cache.sg_canz = 1;
} else {
@@ -239,7 +240,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
add_size = pcmd->u.raw.sdlen;
if (ha->raw_feat & SCATTER_GATHER) {
ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr;
- pcmd->u.raw.sdata = -1UL;
+ pcmd->u.raw.sdata = 0xffffffff;
pcmd->u.raw.sg_lst[0].sg_len = add_size;
pcmd->u.raw.sg_ranz = 1;
} else {
@@ -249,10 +250,9 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
} else {
return(-EINVAL);
}
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) + add_size ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str) + add_size;
if (add_size > 0) {
@@ -265,33 +265,33 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
scp.request.rq_status = RQ_SCSI_BUSY;
scp.request.sem = &sem;
scp.SCp.this_residual = IOCTL_PRI;
+ GDTH_LOCK_SCSI_DOCMD();
scsi_do_cmd(&scp, cmnd, pcmd,
sizeof(gdth_cmd_str), gdth_scsi_done,
piowr->timeout*HZ, 1);
+ GDTH_UNLOCK_SCSI_DOCMD();
down(&sem);
- piord->status = (ulong)scp.SCp.Message;
+ piord->status = (ulong32)scp.SCp.Message;
}
break;
case GDTIOCTL_DRVERS:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
break;
case GDTIOCTL_CTRTYPE:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
- piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 10);
+ piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10);
} else if (ha->type != GDT_PCIMPR) {
piord->iu.ctrtype.type = (unchar)((ha->stype<<8) + 6);
} else {
@@ -303,20 +303,18 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_CTRCNT:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
piord->iu.ctrcnt.count = (ushort)gdth_ctr_count;
break;
case GDTIOCTL_OSVERS:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16);
@@ -325,39 +323,24 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_LOCKDRV:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
- for (i = k = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
- found = FALSE;
- for (j = 0; j < ha->bus_cnt; ++j) {
- for (k = 0; k < MAXID; ++k) {
- if (ha->id[j][k].type == CACHE_DTYP &&
- ha->id[j][k].hostdrive == piowr->iu.lockdrv.drives[i]) {
- found = TRUE;
- break;
- }
- }
- if (found)
- break;
- }
- if (!found)
+ piord = (gdth_iord_str *)ha->pscratch;
+ for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
+ j = piowr->iu.lockdrv.drives[i];
+ if (j >= MAX_HDRIVES || !ha->hdr[j].present)
continue;
-
if (piowr->iu.lockdrv.lock) {
- save_flags( flags );
- cli();
- ha->id[j][k].lock = 1;
- restore_flags( flags );
- gdth_wait_completion( hanum, j, k );
- gdth_stop_timeout( hanum, j, k );
+ GDTH_LOCK_HA(ha, flags);
+ ha->hdr[j].lock = 1;
+ GDTH_UNLOCK_HA(ha, flags);
+ gdth_wait_completion( hanum, ha->bus_cnt, j );
+ gdth_stop_timeout( hanum, ha->bus_cnt, j );
} else {
- save_flags( flags );
- cli();
- ha->id[j][k].lock = 0;
- restore_flags( flags );
- gdth_start_timeout( hanum, j, k );
+ GDTH_LOCK_HA(ha, flags);
+ ha->hdr[j].lock = 0;
+ GDTH_UNLOCK_HA(ha, flags);
+ gdth_start_timeout( hanum, ha->bus_cnt, j );
gdth_next( hanum );
}
}
@@ -366,46 +349,54 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
break;
case GDTIOCTL_LOCKCHN:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- for (k = 0, j = piowr->iu.lockchn.channel; k < MAXID; ++k) {
- if (ha->id[j][k].type != RAW_DTYP)
- continue;
-
+ i = piowr->iu.lockchn.channel;
+ if (i < ha->bus_cnt) {
if (piowr->iu.lockchn.lock) {
- save_flags( flags );
- cli();
- ha->id[j][k].lock = 1;
- restore_flags( flags );
- gdth_wait_completion( hanum, j, k );
- gdth_stop_timeout( hanum, j, k );
+ GDTH_LOCK_HA(ha, flags);
+ ha->raw[i].lock = 1;
+ GDTH_UNLOCK_HA(ha, flags);
+ for (j = 0; j < ha->tid_cnt; ++j) {
+ gdth_wait_completion( hanum, i, j );
+ gdth_stop_timeout( hanum, i, j );
+ }
} else {
- save_flags( flags );
- cli();
- ha->id[j][k].lock = 0;
- restore_flags( flags );
- gdth_start_timeout( hanum, j, k );
- gdth_next( hanum );
+ GDTH_LOCK_HA(ha, flags);
+ ha->raw[i].lock = 0;
+ GDTH_UNLOCK_HA(ha, flags);
+ for (j = 0; j < ha->tid_cnt; ++j) {
+ gdth_start_timeout( hanum, i, j );
+ gdth_next( hanum );
+ }
}
}
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
break;
case GDTIOCTL_EVENT:
- id = gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) );
- if (id == -1)
+ if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) ))
return(-EBUSY);
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
- if (piowr->iu.event.erase == 0) {
- piord->iu.event.handle = gdth_read_event( piowr->iu.event.handle,
- (gdth_evt_str *)piord->iu.event.evt );
+ piord = (gdth_iord_str *)ha->pscratch;
+ if (piowr->iu.event.erase == 0xff) {
+ gdth_store_event(ha,
+ ((gdth_evt_str *)piowr->iu.event.evt)->event_source,
+ ((gdth_evt_str *)piowr->iu.event.evt)->event_idx,
+ &((gdth_evt_str *)piowr->iu.event.evt)->event_data);
+ if (((gdth_evt_str *)piowr->iu.event.evt)->event_source == ES_ASYNC)
+ gdth_log_event(&((gdth_evt_str *)piowr->iu.event.evt)->event_data);
+ } else if (piowr->iu.event.erase == 0xfe) {
+ gdth_clear_events();
+ } else if (piowr->iu.event.erase == 0) {
+ piord->iu.event.handle =
+ gdth_read_event(ha,piowr->iu.event.handle,
+ (gdth_evt_str *)piord->iu.event.evt);
} else {
piord->iu.event.handle = piowr->iu.event.handle;
- gdth_readapp_event( (unchar)piowr->iu.event.erase,
- (gdth_evt_str *)piord->iu.event.evt );
+ gdth_readapp_event(ha, (unchar)piowr->iu.event.erase,
+ (gdth_evt_str *)piord->iu.event.evt);
}
piord->size = sizeof(gdth_iord_str);
piord->status = S_OK;
@@ -415,7 +406,7 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
return(-EINVAL);
}
/* we return a buffer ID to detect the right buffer during READ-IOCTL */
- return id;
+ return 1;
}
static int gdth_get_info(char *buffer,char **start,off_t offset,
@@ -432,15 +423,15 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
id = length;
/* look for buffer ID in length */
- if (id > 4) {
+ if (id > 1) {
#if LINUX_VERSION_CODE >= 0x020000
size = sprintf(buffer+len,
- "%s SCSI Disk Array Controller\n",
- gdth_ctr_name(hanum));
+ "%s Disk Array Controller\n",
+ ha->ctr_name);
#else
size = sprintf(buffer+len,
- "%s SCSI Disk Array Controller (SCSI Bus %d)\n",
- gdth_ctr_name(hanum),busnum);
+ "%s Disk Array Controller (Bus %d)\n",
+ ha->ctr_name,busnum);
#endif
len += size; pos = begin + len;
size = sprintf(buffer+len,
@@ -457,12 +448,12 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
goto stop_output;
} else {
- piord = (gdth_iord_str *)gdth_ioctl_tab[id-1][hanum];
+ piord = (gdth_iord_str *)ha->pscratch;
if (piord == NULL)
goto stop_output;
length = piord->size;
memcpy(buffer+len, (char *)piord, length);
- gdth_ioctl_free(hanum, id);
+ gdth_ioctl_free(hanum);
len += length; pos = begin + len;
if (pos < offset) {
@@ -479,7 +470,7 @@ stop_output:
if (len > length)
len = length;
TRACE2(("get_info() len %d pos %d begin %d offset %d length %d size %d\n",
- len,pos,begin,offset,length,size));
+ len,(int)pos,(int)begin,(int)offset,length,size));
return(len);
}
@@ -496,140 +487,152 @@ void gdth_scsi_done(Scsi_Cmnd *scp)
static int gdth_ioctl_alloc(int hanum, ushort size)
{
+ gdth_ha_str *ha;
ulong flags;
- int i;
+ int ret_val;
- if (size == 0)
+ if (size == 0 || size > GDTH_SCRATCH)
return -1;
- save_flags(flags);
- cli();
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
- for (i = 0; i < 4; ++i) {
- if (gdth_ioctl_tab[i][hanum] == NULL) {
- gdth_ioctl_tab[i][hanum] = kmalloc( size, GFP_ATOMIC | GFP_DMA );
- break;
- }
- }
+ if (!ha->scratch_busy) {
+ ha->scratch_busy = TRUE;
+ ret_val = TRUE;
+ } else
+ ret_val = FALSE;
- restore_flags(flags);
- if (i == 4 || gdth_ioctl_tab[i][hanum] == NULL)
- return -1;
- return (i+1);
+ GDTH_UNLOCK_HA(ha, flags);
+ return ret_val;
}
-static void gdth_ioctl_free(int hanum, int idx)
+static void gdth_ioctl_free(int hanum)
{
+ gdth_ha_str *ha;
ulong flags;
- save_flags(flags);
- cli();
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
- kfree( gdth_ioctl_tab[idx-1][hanum] );
- gdth_ioctl_tab[idx-1][hanum] = NULL;
+ ha->scratch_busy = FALSE;
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
}
static void gdth_wait_completion(int hanum, int busnum, int id)
{
+ gdth_ha_str *ha;
ulong flags;
int i;
Scsi_Cmnd *scp;
- save_flags(flags);
- cli();
+ ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
for (i = 0; i < GDTH_MAXCMDS; ++i) {
- scp = gdth_cmd_tab[i][hanum].cmnd;
- if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
+ scp = ha->cmd_tab[i].cmnd;
#if LINUX_VERSION_CODE >= 0x020000
+ if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
scp->channel == (unchar)busnum)
#else
+ if (!SPECIAL_SCP(scp) && scp->target == (unchar)id &&
NUMDATA(scp->host)->busnum == (unchar)busnum)
#endif
{
- restore_flags(flags);
+ scp->SCp.have_data_in = 0;
+ GDTH_UNLOCK_HA(ha, flags);
while (!scp->SCp.have_data_in)
barrier();
- save_flags(flags);
- cli();
+ GDTH_LOCK_SCSI_DONE(flags);
+ scp->scsi_done(scp);
+ GDTH_UNLOCK_SCSI_DONE(flags);
+ GDTH_LOCK_HA(ha, flags);
}
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
}
static void gdth_stop_timeout(int hanum, int busnum, int id)
{
+ gdth_ha_str *ha;
ulong flags;
Scsi_Cmnd *scp;
- gdth_ha_str *ha;
- save_flags(flags);
- cli();
ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
- if (scp->target == (unchar)id &&
#if LINUX_VERSION_CODE >= 0x020000
+ if (scp->target == (unchar)id &&
scp->channel == (unchar)busnum)
#else
+ if (scp->target == (unchar)id &&
NUMDATA(scp->host)->busnum == (unchar)busnum)
#endif
{
TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
- scp->SCp.buffers_residual = gdth_update_timeout(scp, 0);
+ scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
}
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
}
static void gdth_start_timeout(int hanum, int busnum, int id)
{
+ gdth_ha_str *ha;
ulong flags;
Scsi_Cmnd *scp;
- gdth_ha_str *ha;
- save_flags(flags);
- cli();
ha = HADATA(gdth_ctr_tab[hanum]);
+ GDTH_LOCK_HA(ha, flags);
for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
- if (scp->target == (unchar)id &&
#if LINUX_VERSION_CODE >= 0x020000
+ if (scp->target == (unchar)id &&
scp->channel == (unchar)busnum)
#else
+ if (scp->target == (unchar)id &&
NUMDATA(scp->host)->busnum == (unchar)busnum)
#endif
{
TRACE2(("gdth_start_timeout(): update_timeout()\n"));
- gdth_update_timeout(scp, scp->SCp.buffers_residual);
+ gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
}
}
- restore_flags(flags);
+ GDTH_UNLOCK_HA(ha, flags);
}
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout)
+static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout)
{
- ulong flags;
int oldto;
- save_flags(flags);
- cli();
+ oldto = scp->timeout_per_command;
+ scp->timeout_per_command = timeout;
- oldto = scp->timeout;
- scp->timeout = timeout;
+#if LINUX_VERSION_CODE >= 0x02014B
+ if (timeout == 0) {
+ del_timer(&scp->eh_timeout);
+ scp->eh_timeout.data = (unsigned long) NULL;
+ scp->eh_timeout.expires = 0;
+ } else {
+ if (scp->eh_timeout.data != (unsigned long) NULL)
+ del_timer(&scp->eh_timeout);
+ scp->eh_timeout.data = (unsigned long) scp;
+ scp->eh_timeout.expires = jiffies + timeout;
+ add_timer(&scp->eh_timeout);
+ }
+#else
if (timeout > 0) {
- if (timer_table[GDTH_TIMER].expires == 0) {
- timer_table[GDTH_TIMER].expires = jiffies + timeout;
- timer_active |= 1 << GDTH_TIMER;
+ if (timer_table[SCSI_TIMER].expires == 0) {
+ timer_table[SCSI_TIMER].expires = jiffies + timeout;
+ timer_active |= 1 << SCSI_TIMER;
} else {
- if (jiffies + timeout < timer_table[GDTH_TIMER].expires)
- timer_table[GDTH_TIMER].expires = jiffies + timeout;
+ if (jiffies + timeout < timer_table[SCSI_TIMER].expires)
+ timer_table[SCSI_TIMER].expires = jiffies + timeout;
}
}
+#endif
- restore_flags(flags);
return oldto;
}
-
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index a3d5dcd71..00c18622d 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -2,7 +2,7 @@
#define _GDTH_PROC_H
/* gdth_proc.h
- * $Id: gdth_proc.h,v 1.2 1997/02/21 08:08:51 achim Exp $
+ * $Id: gdth_proc.h,v 1.5 1998/12/17 15:43:53 achim Exp $
*/
static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
@@ -12,11 +12,11 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,
int length,int vh,int hanum,int busnum);
static int gdth_ioctl_alloc(int hanum, ushort size);
-static void gdth_ioctl_free(int hanum, int id);
+static void gdth_ioctl_free(int hanum);
static void gdth_wait_completion(int hanum, int busnum, int id);
static void gdth_stop_timeout(int hanum, int busnum, int id);
static void gdth_start_timeout(int hanum, int busnum, int id);
-static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout);
+static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
void gdth_scsi_done(Scsi_Cmnd *scp);
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index a818d5961..58698132b 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -7,6 +7,8 @@
* Subsequent revisions: Eric Youngdale
*
* <drew@colorado.edu>
+ *
+ * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
*/
@@ -97,6 +99,18 @@
#include "atari_scsi.h"
#endif
+#ifdef CONFIG_MAC_SCSI_OLD
+#include "mac_scsi.h"
+#endif
+
+#ifdef CONFIG_MAC_SCSI
+#include "mac_scsinew.h"
+#endif
+
+#ifdef CONFIG_SCSI_MAC_ESP
+#include "mac_esp.h"
+#endif
+
#ifdef CONFIG_SCSI_ADVANSYS
#include "advansys.h"
#endif
@@ -161,6 +175,10 @@
#include "qlogicisp.h"
#endif
+#ifdef CONFIG_SCSI_QLOGIC_FC
+#include "qlogicfc.h"
+#endif
+
#ifdef CONFIG_SCSI_SEAGATE
#include "seagate.h"
#endif
@@ -189,6 +207,10 @@
#include "wd7000.h"
#endif
+#ifdef CONFIG_SCSI_MCA_53C9X
+#include "mca_53c9x.h"
+#endif
+
#ifdef CONFIG_SCSI_IBMMCA
#include "ibmmca.h"
#endif
@@ -209,6 +231,14 @@
#include "AM53C974.h"
#endif
+#ifdef CONFIG_SCSI_MEGARAID
+#include "megaraid.h"
+#endif
+
+#ifdef CONFIG_SCSI_ACARD
+#include "atp870u.h"
+#endif
+
#ifdef CONFIG_SCSI_SUNESP
#include "sparc_esp.h"
#endif
@@ -253,6 +283,10 @@
#include "pluto.h"
#endif
+#ifdef CONFIG_SCSI_INITIO
+#include "ini9100u.h"
+#endif
+
#ifdef CONFIG_SCSI_DEBUG
#include "scsi_debug.h"
#endif
@@ -372,6 +406,18 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#endif
#endif
+#ifdef CONFIG_MAC
+#ifdef CONFIG_MAC_SCSI_OLD
+ MAC_SCSI,
+#endif
+#ifdef CONFIG_SCSI_MAC_ESP
+ SCSI_MAC_ESP,
+#endif
+#ifdef CONFIG_MAC_SCSI
+ MAC_NCR5380,
+#endif
+#endif
+
#ifdef CONFIG_MVME16x_SCSI
MVME16x_SCSI,
#endif
@@ -414,6 +460,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_AIC7XXX
AIC7XXX,
#endif
+#ifdef CONFIG_FD_MCS
+ FD_MCS,
+#endif
#ifdef CONFIG_SCSI_FUTURE_DOMAIN
FDOMAIN_16X0,
#endif
@@ -432,6 +481,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_QLOGIC_ISP
QLOGICISP,
#endif
+#ifdef CONFIG_SCSI_QLOGIC_FC
+ QLOGICFC,
+#endif
#ifdef CONFIG_SCSI_PAS16
MV_PAS16,
#endif
@@ -459,6 +511,9 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_7000FASST
WD7000,
#endif
+#ifdef CONFIG_SCSI_MCA_53C9X
+ MCA_53C9X,
+#endif
#ifdef CONFIG_SCSI_IBMMCA
IBMMCA,
#endif
@@ -471,12 +526,21 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
#ifdef CONFIG_SCSI_AM53C974
AM53C974,
#endif
+#ifdef CONFIG_SCSI_MEGARAID
+ MEGARAID,
+#endif
+#ifdef CONFIG_SCSI_ACARD
+ ATP870U,
+#endif
#ifdef CONFIG_SCSI_SUNESP
SCSI_SPARC_ESP,
#endif
#ifdef CONFIG_SCSI_GDTH
GDTH,
#endif
+#ifdef CONFIG_SCSI_INITIO
+ INI9100U,
+#endif
#ifdef CONFIG_SCSI_QLOGICPTI
QLOGICPTI,
#endif
@@ -595,6 +659,7 @@ struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
next_scsi_host++;
retval->host_queue = NULL;
retval->host_wait = NULL;
+ retval->resetting = 0;
retval->last_reset = 0;
retval->irq = 0;
retval->dma_channel = 0xff;
diff --git a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h
index 1ed41771b..393d03f4e 100644
--- a/drivers/scsi/hosts.h
+++ b/drivers/scsi/hosts.h
@@ -14,6 +14,8 @@
*
* Further modified by Eric Youngdale to support multiple host adapters
* of the same type.
+ *
+ * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
*/
#ifndef _HOSTS_H
@@ -320,6 +322,7 @@ struct Scsi_Host
/* public: */
unsigned short extra_bytes;
unsigned short host_no; /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
+ int resetting; /* if set, it means that last_reset is a valid value */
unsigned long last_reset;
@@ -379,7 +382,14 @@ struct Scsi_Host
* Host has rejected a command because it was busy.
*/
unsigned host_blocked:1;
+
+ /*
+ * Host uses correct SCSI ordering not PC ordering. The bit is
+ * set for the minority of drivers whose authors actually read the spec ;)
+ */
+ unsigned reverse_ordering:1;
+
void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
/*
diff --git a/drivers/scsi/i91uscsi.c b/drivers/scsi/i91uscsi.c
new file mode 100644
index 000000000..088a2f19e
--- /dev/null
+++ b/drivers/scsi/i91uscsi.c
@@ -0,0 +1,2808 @@
+/**************************************************************************
+ * Initio 9100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 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 name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
+ *
+ ************************************************************************
+ Module: i91uscsi.c
+ Description: PCI I/F for INI-910 SCSI Bus Master Controller
+ Revision History:
+ 11/09/94 Tim Chen, Initiali Version 0.90A
+ 01/17/95 TC, release ver 1.01
+ 02/09/95 TC modify ReadPCIConfig, try both mechanisms;
+ 02/15/95 TC add support for INI-9100W
+ 06/04/96 HC, Change to fit LINUX from jaspci.c
+ 11/18/96 HC, Port for tulip
+ 07/08/98 hc, Support 0002134A
+ 07/23/98 wh, Change the abort_srb routine.
+ 09/16/98 hl, Support ALPHA, Rewrite the returnNumberAdapters <01>
+ 12/09/98 bv, Removed unused code, changed tul_se2_wait to
+ use udelay(30) and tul_do_pause to enable
+ interrupts for >= 2.1.95
+ 12/13/98 bv, Use spinlocks instead of cli() for serialized
+ access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail
+ members of the HCS structure.
+ 01/09/98 bv, Fix a deadlock on SMP system.
+**********************************************************************/
+
+#define DEBUG_INTERRUPT 0
+#define DEBUG_QUEUE 0
+#define DEBUG_STATE 0
+#define INT_DISC 0
+
+
+#ifndef CVT_LINUX_VERSION
+#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
+#endif
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/blk.h>
+#include <asm/io.h>
+
+#include "i91uscsi.h"
+
+/*--- external functions --*/
+static void tul_se2_wait(void);
+
+/*--- forward refrence ---*/
+static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
+static SCB *tul_find_done_scb(HCS * pCurHcb);
+
+static int tulip_main(HCS * pCurHcb);
+
+static int tul_next_state(HCS * pCurHcb);
+static int tul_state_1(HCS * pCurHcb);
+static int tul_state_2(HCS * pCurHcb);
+static int tul_state_3(HCS * pCurHcb);
+static int tul_state_4(HCS * pCurHcb);
+static int tul_state_5(HCS * pCurHcb);
+static int tul_state_6(HCS * pCurHcb);
+static int tul_state_7(HCS * pCurHcb);
+static int tul_xfer_data_in(HCS * pCurHcb);
+static int tul_xfer_data_out(HCS * pCurHcb);
+static int tul_xpad_in(HCS * pCurHcb);
+static int tul_xpad_out(HCS * pCurHcb);
+static int tul_status_msg(HCS * pCurHcb);
+
+static int tul_msgin(HCS * pCurHcb);
+static int tul_msgin_sync(HCS * pCurHcb);
+static int tul_msgin_accept(HCS * pCurHcb);
+static int tul_msgout_reject(HCS * pCurHcb);
+static int tul_msgin_extend(HCS * pCurHcb);
+
+static int tul_msgout_ide(HCS * pCurHcb);
+static int tul_msgout_abort_targ(HCS * pCurHcb);
+static int tul_msgout_abort_tag(HCS * pCurHcb);
+
+static int tul_bus_device_reset(HCS * pCurHcb);
+static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
+static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
+static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
+static int int_tul_busfree(HCS * pCurHcb);
+int int_tul_scsi_rst(HCS * pCurHcb);
+static int int_tul_bad_seq(HCS * pCurHcb);
+static int int_tul_resel(HCS * pCurHcb);
+static int tul_sync_done(HCS * pCurHcb);
+static int wdtr_done(HCS * pCurHcb);
+static int wait_tulip(HCS * pCurHcb);
+static int tul_wait_done_disc(HCS * pCurHcb);
+static int tul_wait_disc(HCS * pCurHcb);
+static void tulip_scsi(HCS * pCurHcb);
+static int tul_post_scsi_rst(HCS * pCurHcb);
+
+static void tul_se2_ew_en(WORD CurBase);
+static void tul_se2_ew_ds(WORD CurBase);
+static int tul_se2_rd_all(WORD CurBase);
+static void tul_se2_update_all(WORD CurBase); /* setup default pattern */
+static void tul_read_eeprom(WORD CurBase);
+
+ /* ---- EXTERNAL VARIABLES ---- */
+HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
+ /* ---- INTERNAL VARIABLES ---- */
+static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
+
+/*NVRAM nvram, *nvramp = &nvram; */
+static NVRAM i91unvram;
+static NVRAM *i91unvramp;
+
+
+
+static UCHAR i91udftNvRam[64] =
+{
+/*----------- header -----------*/
+ 0x25, 0xc9, /* Signature */
+ 0x40, /* Size */
+ 0x01, /* Revision */
+ /* -- Host Adapter Structure -- */
+ 0x95, /* ModelByte0 */
+ 0x00, /* ModelByte1 */
+ 0x00, /* ModelInfo */
+ 0x01, /* NumOfCh */
+ NBC1_DEFAULT, /* BIOSConfig1 */
+ 0, /* BIOSConfig2 */
+ 0, /* HAConfig1 */
+ 0, /* HAConfig2 */
+ /* SCSI channel 0 and target Structure */
+ 7, /* SCSIid */
+ NCC1_DEFAULT, /* SCSIconfig1 */
+ 0, /* SCSIconfig2 */
+ 0x10, /* NumSCSItarget */
+
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+
+ /* SCSI channel 1 and target Structure */
+ 7, /* SCSIid */
+ NCC1_DEFAULT, /* SCSIconfig1 */
+ 0, /* SCSIconfig2 */
+ 0x10, /* NumSCSItarget */
+
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0}; /* - CheckSum - */
+
+
+static UCHAR tul_rate_tbl[8] = /* fast 20 */
+{
+ /* nanosecond devide by 4 */
+ 12, /* 50ns, 20M */
+ 18, /* 75ns, 13.3M */
+ 25, /* 100ns, 10M */
+ 31, /* 125ns, 8M */
+ 37, /* 150ns, 6.6M */
+ 43, /* 175ns, 5.7M */
+ 50, /* 200ns, 5M */
+ 62 /* 250ns, 4M */
+};
+
+extern int tul_num_ch;
+
+
+static void tul_do_pause(unsigned amount)
+{ /* Pause for amount*10 milliseconds */
+ unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ while (time_before_eq(jiffies, the_time));
+#else
+ while (jiffies < the_time);
+#endif
+}
+
+/*-- forward reference --*/
+
+/*******************************************************************
+ Use memeory refresh time ~ 15us * 2
+********************************************************************/
+void tul_se2_wait()
+{
+#if 1
+ udelay(30);
+#else
+ UCHAR readByte;
+
+ readByte = TUL_RD(0, 0x61);
+ if ((readByte & 0x10) == 0x10) {
+ for (;;) {
+ readByte = TUL_RD(0, 0x61);
+ if ((readByte & 0x10) == 0x10)
+ break;
+ }
+ for (;;) {
+ readByte = TUL_RD(0, 0x61);
+ if ((readByte & 0x10) != 0x10)
+ break;
+ }
+ } else {
+ for (;;) {
+ readByte = TUL_RD(0, 0x61);
+ if ((readByte & 0x10) == 0x10)
+ break;
+ }
+ for (;;) {
+ readByte = TUL_RD(0, 0x61);
+ if ((readByte & 0x10) != 0x10)
+ break;
+ }
+ }
+#endif
+}
+
+
+/******************************************************************
+ Input: instruction for Serial E2PROM
+
+ EX: se2_rd(0 call se2_instr() to send address and read command
+
+ StartBit OP_Code Address Data
+ --------- -------- ------------------ -------
+ 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0
+
+ +-----------------------------------------------------
+ |
+ CS -----+
+ +--+ +--+ +--+ +--+ +--+
+ ^ | ^ | ^ | ^ | ^ |
+ | | | | | | | | | |
+ CLK -------+ +--+ +--+ +--+ +--+ +--
+ (leading edge trigger)
+
+ +--1-----1--+
+ | SB OP | OP A5 A4
+ DI ----+ +--0------------------
+ (address and cmd sent to nvram)
+
+ -------------------------------------------+
+ |
+ DO +---
+ (data sent from nvram)
+
+
+******************************************************************/
+void tul_se2_instr(WORD CurBase, UCHAR instr)
+{
+ int i;
+ UCHAR b;
+
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* cs+start bit */
+ tul_se2_wait();
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO); /* +CLK */
+ tul_se2_wait();
+
+ for (i = 0; i < 8; i++) {
+ if (instr & 0x80)
+ b = SE2CS | SE2DO; /* -CLK+dataBit */
+ else
+ b = SE2CS; /* -CLK */
+ TUL_WR(CurBase + TUL_NVRAM, b);
+ tul_se2_wait();
+ TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK); /* +CLK */
+ tul_se2_wait();
+ instr <<= 1;
+ }
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */
+ tul_se2_wait();
+ return;
+}
+
+
+/******************************************************************
+ Function name : tul_se2_ew_en
+ Description : Enable erase/write state of serial EEPROM
+******************************************************************/
+void tul_se2_ew_en(WORD CurBase)
+{
+ tul_se2_instr(CurBase, 0x30); /* EWEN */
+ TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */
+ tul_se2_wait();
+ return;
+}
+
+
+/************************************************************************
+ Disable erase/write state of serial EEPROM
+*************************************************************************/
+void tul_se2_ew_ds(WORD CurBase)
+{
+ tul_se2_instr(CurBase, 0); /* EWDS */
+ TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */
+ tul_se2_wait();
+ return;
+}
+
+
+/******************************************************************
+ Input :address of Serial E2PROM
+ Output :value stored in Serial E2PROM
+*******************************************************************/
+USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+{
+ UCHAR instr, readByte;
+ USHORT readWord;
+ int i;
+
+ instr = (UCHAR) (adr | 0x80);
+ tul_se2_instr(CurBase, instr); /* READ INSTR */
+ readWord = 0;
+
+ for (i = 15; i >= 0; i--) {
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */
+ tul_se2_wait();
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */
+
+ /* sample data after the following edge of clock */
+ readByte = TUL_RD(CurBase, TUL_NVRAM);
+ readByte &= SE2DI;
+ readWord += (readByte << i);
+ tul_se2_wait(); /* 6/20/95 */
+ }
+
+ TUL_WR(CurBase + TUL_NVRAM, 0); /* no chip select */
+ tul_se2_wait();
+ return readWord;
+}
+
+
+/******************************************************************
+ Input: new value in Serial E2PROM, address of Serial E2PROM
+*******************************************************************/
+void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
+{
+ UCHAR readByte;
+ UCHAR instr;
+ int i;
+
+ instr = (UCHAR) (adr | 0x40);
+ tul_se2_instr(CurBase, instr); /* WRITE INSTR */
+ for (i = 15; i >= 0; i--) {
+ if (writeWord & 0x8000)
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO); /* -CLK+dataBit 1 */
+ else
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK+dataBit 0 */
+ tul_se2_wait();
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */
+ tul_se2_wait();
+ writeWord <<= 1;
+ }
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */
+ tul_se2_wait();
+ TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */
+ tul_se2_wait();
+
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* +CS */
+ tul_se2_wait();
+
+ for (;;) {
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK); /* +CLK */
+ tul_se2_wait();
+ TUL_WR(CurBase + TUL_NVRAM, SE2CS); /* -CLK */
+ tul_se2_wait();
+ if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
+ break; /* write complete */
+ }
+ TUL_WR(CurBase + TUL_NVRAM, 0); /* -CS */
+ return;
+}
+
+
+/***********************************************************************
+ Read SCSI H/A configuration parameters from serial EEPROM
+************************************************************************/
+int tul_se2_rd_all(WORD CurBase)
+{
+ int i;
+ ULONG chksum = 0;
+ USHORT *np;
+
+ i91unvramp = &i91unvram;
+ np = (USHORT *) i91unvramp;
+ for (i = 0; i < 32; i++) {
+ *np++ = tul_se2_rd(CurBase, i);
+ }
+
+/*--------------------Is signature "ini" ok ? ----------------*/
+ if (i91unvramp->NVM_Signature != INI_SIGNATURE)
+ return -1;
+/*---------------------- Is ckecksum ok ? ----------------------*/
+ np = (USHORT *) i91unvramp;
+ for (i = 0; i < 31; i++)
+ chksum += *np++;
+ if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
+ return -1;
+ return 1;
+}
+
+
+/***********************************************************************
+ Update SCSI H/A configuration parameters from serial EEPROM
+************************************************************************/
+void tul_se2_update_all(WORD CurBase)
+{ /* setup default pattern */
+ int i;
+ ULONG chksum = 0;
+ USHORT *np, *np1;
+
+ i91unvramp = &i91unvram;
+ /* Calculate checksum first */
+ np = (USHORT *) i91udftNvRam;
+ for (i = 0; i < 31; i++)
+ chksum += *np++;
+ *np = (USHORT) chksum;
+ tul_se2_ew_en(CurBase); /* Enable write */
+
+ np = (USHORT *) i91udftNvRam;
+ np1 = (USHORT *) i91unvramp;
+ for (i = 0; i < 32; i++, np++, np1++) {
+ if (*np != *np1) {
+ tul_se2_wr(CurBase, i, *np);
+ }
+ }
+
+ tul_se2_ew_ds(CurBase); /* Disable write */
+ return;
+}
+
+/*************************************************************************
+ Function name : read_eeprom
+**************************************************************************/
+void tul_read_eeprom(WORD CurBase)
+{
+ UCHAR gctrl;
+
+ i91unvramp = &i91unvram;
+/*------Enable EEProm programming ---*/
+ gctrl = TUL_RD(CurBase, TUL_GCTRL);
+ TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
+ if (tul_se2_rd_all(CurBase) != 1) {
+ tul_se2_update_all(CurBase); /* setup default pattern */
+ tul_se2_rd_all(CurBase); /* load again */
+ }
+/*------ Disable EEProm programming ---*/
+ gctrl = TUL_RD(CurBase, TUL_GCTRL);
+ TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
+} /* read_eeprom */
+
+int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
+ BYTE bBus, BYTE bDevice)
+{
+ int i, j;
+
+ for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
+ if (i91u_adpt[i].ADPT_BIOS < wBIOS)
+ continue;
+ if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
+ if (i91u_adpt[i].ADPT_BASE == wBASE) {
+ if (i91u_adpt[i].ADPT_Bus != 0xFF)
+ return (FAILURE);
+ } else if (i91u_adpt[i].ADPT_BASE < wBASE)
+ continue;
+ }
+ for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
+ i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
+ i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
+ i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
+ i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
+ i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
+ }
+ i91u_adpt[i].ADPT_BASE = wBASE;
+ i91u_adpt[i].ADPT_INTR = bInterrupt;
+ i91u_adpt[i].ADPT_BIOS = wBIOS;
+ i91u_adpt[i].ADPT_Bus = bBus;
+ i91u_adpt[i].ADPT_Device = bDevice;
+ return (SUCCESSFUL);
+ }
+ return (FAILURE);
+}
+
+void init_i91uAdapter_table(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */
+ i91u_adpt[i].ADPT_BIOS = 0xffff;
+ i91u_adpt[i].ADPT_BASE = 0xffff;
+ i91u_adpt[i].ADPT_INTR = 0xff;
+ i91u_adpt[i].ADPT_Bus = 0xff;
+ i91u_adpt[i].ADPT_Device = 0xff;
+ }
+ return;
+}
+
+void tul_stop_bm(HCS * pCurHcb)
+{
+
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+ /* wait Abort DMA xfer done */
+ while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+}
+
+/***************************************************************************/
+void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
+{
+ pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE; /* Supply base address */
+ pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */
+ pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */
+ return;
+}
+
+/***************************************************************************/
+int tul_reset_scsi(HCS * pCurHcb, int seconds)
+{
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
+
+ while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
+ /* reset tulip chip */
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
+
+ /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
+ /* SONY 5200 tape drive won't work if only stall for 1 sec */
+ tul_do_pause(seconds * 100);
+
+ TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+
+ return (SCSI_RESET_SUCCESS);
+}
+
+/***************************************************************************/
+int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
+{
+ int i;
+ WORD *pwFlags;
+ BYTE *pbHeads;
+ SCB *pTmpScb, *pPrevScb = NULL;
+
+ pCurHcb->HCS_NumScbs = tul_num_scb;
+ pCurHcb->HCS_Semaph = 1;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ pCurHcb->HCS_SemaphLock = SPIN_LOCK_UNLOCKED;
+#endif
+ pCurHcb->HCS_JSStatus0 = 0;
+ pCurHcb->HCS_Scb = scbp;
+ pCurHcb->HCS_NxtPend = scbp;
+ pCurHcb->HCS_NxtAvail = scbp;
+ for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
+ pTmpScb->SCB_TagId = i;
+ if (i != 0)
+ pPrevScb->SCB_NxtScb = pTmpScb;
+ pPrevScb = pTmpScb;
+ }
+ pPrevScb->SCB_NxtScb = NULL;
+ pCurHcb->HCS_ScbEnd = pTmpScb;
+ pCurHcb->HCS_FirstAvail = scbp;
+ pCurHcb->HCS_LastAvail = pPrevScb;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ pCurHcb->HCS_AvailLock = SPIN_LOCK_UNLOCKED;
+#endif
+ pCurHcb->HCS_FirstPend = NULL;
+ pCurHcb->HCS_LastPend = NULL;
+ pCurHcb->HCS_FirstBusy = NULL;
+ pCurHcb->HCS_LastBusy = NULL;
+ pCurHcb->HCS_FirstDone = NULL;
+ pCurHcb->HCS_LastDone = NULL;
+ pCurHcb->HCS_ActScb = NULL;
+ pCurHcb->HCS_ActTcs = NULL;
+
+ tul_read_eeprom(pCurHcb->HCS_Base);
+/*---------- get H/A configuration -------------*/
+ if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
+ pCurHcb->HCS_MaxTar = 8;
+ else
+ pCurHcb->HCS_MaxTar = 16;
+
+ pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
+
+ pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
+ pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
+
+#if CHK_PARITY
+ /* Enable parity error response */
+ TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
+#endif
+
+ /* Mask all the interrupt */
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+
+ tul_stop_bm(pCurHcb);
+ /* --- Initialize the tulip --- */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
+
+ /* program HBA's SCSI ID */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
+
+ /* Enable Initiator Mode ,phase latch,alternate sync period mode,
+ disable SCSI reset */
+ if (pCurHcb->HCS_Config & HCC_EN_PAR)
+ pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
+ else
+ pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
+
+ /* Enable HW reselect */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
+
+ /* selection time out = 250 ms */
+ TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
+
+/*--------- Enable SCSI terminator -----*/
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
+ TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
+ ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
+
+ for (i = 0,
+ pwFlags = (WORD *) & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
+ pbHeads = pbBiosAdr + 0x180;
+ i < pCurHcb->HCS_MaxTar;
+ i++, pwFlags++) {
+ pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+ if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
+ pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+ else
+ pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
+ pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
+ pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
+ pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
+ if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
+ pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+ else
+ pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
+ pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
+ pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
+ pCurHcb->HCS_ActTags[i] = 0;
+ pCurHcb->HCS_MaxTags[i] = 0xFF;
+ } /* for */
+ printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
+ pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
+ pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
+/*------------------- reset SCSI Bus ---------------------------*/
+ if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
+ printk("i91u: Reset SCSI Bus ... \n");
+ tul_reset_scsi(pCurHcb, seconds);
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
+ return (0);
+}
+
+/***************************************************************************/
+SCB *tul_alloc_scb(HCS * hcsp)
+{
+ SCB *pTmpScb;
+ ULONG flags;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+ if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
+#if DEBUG_QUEUE
+ printk("find scb at %08lx\n", (ULONG) pTmpScb);
+#endif
+ if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
+ hcsp->HCS_LastAvail = NULL;
+ pTmpScb->SCB_NxtScb = NULL;
+ pTmpScb->SCB_Status = SCB_RENT;
+ }
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return (pTmpScb);
+}
+
+/***************************************************************************/
+void tul_release_scb(HCS * hcsp, SCB * scbp)
+{
+ ULONG flags;
+
+#if DEBUG_QUEUE
+ printk("Release SCB %lx; ", (ULONG) scbp);
+#endif
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+ scbp->SCB_Srb = 0;
+ scbp->SCB_Status = 0;
+ scbp->SCB_NxtScb = NULL;
+ if (hcsp->HCS_LastAvail != NULL) {
+ hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
+ hcsp->HCS_LastAvail = scbp;
+ } else {
+ hcsp->HCS_FirstAvail = scbp;
+ hcsp->HCS_LastAvail = scbp;
+ }
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
+#else
+ restore_flags(flags);
+#endif
+}
+
+/***************************************************************************/
+void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+ printk("Append pend SCB %lx; ", (ULONG) scbp);
+#endif
+ scbp->SCB_Status = SCB_PEND;
+ scbp->SCB_NxtScb = NULL;
+ if (pCurHcb->HCS_LastPend != NULL) {
+ pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
+ pCurHcb->HCS_LastPend = scbp;
+ } else {
+ pCurHcb->HCS_FirstPend = scbp;
+ pCurHcb->HCS_LastPend = scbp;
+ }
+}
+
+/***************************************************************************/
+void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+ printk("Push pend SCB %lx; ", (ULONG) scbp);
+#endif
+ scbp->SCB_Status = SCB_PEND;
+ if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
+ pCurHcb->HCS_FirstPend = scbp;
+ } else {
+ pCurHcb->HCS_FirstPend = scbp;
+ pCurHcb->HCS_LastPend = scbp;
+ }
+}
+
+/***************************************************************************/
+SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+{
+ SCB *pFirstPend;
+
+
+ pFirstPend = pCurHcb->HCS_FirstPend;
+ while (pFirstPend != NULL) {
+ if (pFirstPend->SCB_Opcode != ExecSCSI) {
+ return (pFirstPend);
+ }
+ if (pFirstPend->SCB_TagMsg == 0) {
+ if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
+ !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
+ return (pFirstPend);
+ }
+ } else {
+ if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
+ pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
+ (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
+ pFirstPend = pFirstPend->SCB_NxtScb;
+ continue;
+ }
+ return (pFirstPend);
+ }
+ pFirstPend = pFirstPend->SCB_NxtScb;
+ }
+
+
+ return (pFirstPend);
+}
+/***************************************************************************/
+SCB *tul_pop_pend_scb(HCS * pCurHcb)
+{
+ SCB *pTmpScb;
+
+ if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) {
+ if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastPend = NULL;
+ pTmpScb->SCB_NxtScb = NULL;
+ }
+#if DEBUG_QUEUE
+ printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);
+#endif
+ return (pTmpScb);
+}
+
+
+/***************************************************************************/
+void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+{
+ SCB *pTmpScb, *pPrevScb;
+
+#if DEBUG_QUEUE
+ printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
+#endif
+
+ pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
+ while (pTmpScb != NULL) {
+ if (pCurScb == pTmpScb) { /* Unlink this SCB */
+ if (pTmpScb == pCurHcb->HCS_FirstPend) {
+ if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastPend = NULL;
+ } else {
+ pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+ if (pTmpScb == pCurHcb->HCS_LastPend)
+ pCurHcb->HCS_LastPend = pPrevScb;
+ }
+ pTmpScb->SCB_NxtScb = NULL;
+ break;
+ }
+ pPrevScb = pTmpScb;
+ pTmpScb = pTmpScb->SCB_NxtScb;
+ }
+ return;
+}
+/***************************************************************************/
+void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+ printk("append busy SCB %lx; ", (ULONG) scbp);
+#endif
+ if (scbp->SCB_TagMsg)
+ pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
+ else
+ pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
+ scbp->SCB_Status = SCB_BUSY;
+ scbp->SCB_NxtScb = NULL;
+ if (pCurHcb->HCS_LastBusy != NULL) {
+ pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
+ pCurHcb->HCS_LastBusy = scbp;
+ } else {
+ pCurHcb->HCS_FirstBusy = scbp;
+ pCurHcb->HCS_LastBusy = scbp;
+ }
+}
+
+/***************************************************************************/
+SCB *tul_pop_busy_scb(HCS * pCurHcb)
+{
+ SCB *pTmpScb;
+
+
+ if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
+ if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastBusy = NULL;
+ pTmpScb->SCB_NxtScb = NULL;
+ if (pTmpScb->SCB_TagMsg)
+ pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+ else
+ pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+ }
+#if DEBUG_QUEUE
+ printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
+#endif
+ return (pTmpScb);
+}
+
+/***************************************************************************/
+void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+{
+ SCB *pTmpScb, *pPrevScb;
+
+#if DEBUG_QUEUE
+ printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
+#endif
+
+ pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
+ while (pTmpScb != NULL) {
+ if (pCurScb == pTmpScb) { /* Unlink this SCB */
+ if (pTmpScb == pCurHcb->HCS_FirstBusy) {
+ if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastBusy = NULL;
+ } else {
+ pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+ if (pTmpScb == pCurHcb->HCS_LastBusy)
+ pCurHcb->HCS_LastBusy = pPrevScb;
+ }
+ pTmpScb->SCB_NxtScb = NULL;
+ if (pTmpScb->SCB_TagMsg)
+ pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+ else
+ pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+ break;
+ }
+ pPrevScb = pTmpScb;
+ pTmpScb = pTmpScb->SCB_NxtScb;
+ }
+ return;
+}
+
+/***************************************************************************/
+SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
+{
+ SCB *pTmpScb, *pPrevScb;
+ WORD scbp_tarlun;
+
+
+ pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
+ while (pTmpScb != NULL) {
+ scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
+ if (scbp_tarlun == tarlun) { /* Unlink this SCB */
+ break;
+ }
+ pPrevScb = pTmpScb;
+ pTmpScb = pTmpScb->SCB_NxtScb;
+ }
+#if DEBUG_QUEUE
+ printk("find busy SCB %lx; ", (ULONG) pTmpScb);
+#endif
+ return (pTmpScb);
+}
+
+/***************************************************************************/
+void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+ printk("append done SCB %lx; ", (ULONG) scbp);
+#endif
+
+ scbp->SCB_Status = SCB_DONE;
+ scbp->SCB_NxtScb = NULL;
+ if (pCurHcb->HCS_LastDone != NULL) {
+ pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
+ pCurHcb->HCS_LastDone = scbp;
+ } else {
+ pCurHcb->HCS_FirstDone = scbp;
+ pCurHcb->HCS_LastDone = scbp;
+ }
+}
+
+/***************************************************************************/
+SCB *tul_find_done_scb(HCS * pCurHcb)
+{
+ SCB *pTmpScb;
+
+
+ if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
+ if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastDone = NULL;
+ pTmpScb->SCB_NxtScb = NULL;
+ }
+#if DEBUG_QUEUE
+ printk("find done SCB %lx; ", (ULONG) pTmpScb);
+#endif
+ return (pTmpScb);
+}
+
+/***************************************************************************/
+int tul_abort_srb(HCS * pCurHcb, ULONG srbp)
+{
+ ULONG flags;
+ SCB *pTmpScb, *pPrevScb;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+
+ if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+ /* disable Jasmin SCSI Int */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ tulip_main(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ pCurHcb->HCS_Semaph = 1;
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+
+ return SCSI_ABORT_SNOOZE;
+ }
+ pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; /* Check Pend queue */
+ while (pTmpScb != NULL) {
+ /* 07/27/98 */
+ if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
+ if (pTmpScb == pCurHcb->HCS_ActScb) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_ABORT_BUSY;
+ } else if (pTmpScb == pCurHcb->HCS_FirstPend) {
+ if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastPend = NULL;
+ } else {
+ pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+ if (pTmpScb == pCurHcb->HCS_LastPend)
+ pCurHcb->HCS_LastPend = pPrevScb;
+ }
+ pTmpScb->SCB_HaStat = HOST_ABORTED;
+ pTmpScb->SCB_Flags |= SCF_DONE;
+ if (pTmpScb->SCB_Flags & SCF_POST)
+ (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_ABORT_SUCCESS;
+ }
+ pPrevScb = pTmpScb;
+ pTmpScb = pTmpScb->SCB_NxtScb;
+ }
+
+ pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */
+ while (pTmpScb != NULL) {
+
+ if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
+
+ if (pTmpScb == pCurHcb->HCS_ActScb) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_ABORT_BUSY;
+ } else if (pTmpScb->SCB_TagMsg == 0) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_ABORT_BUSY;
+ } else {
+ pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+ if (pTmpScb == pCurHcb->HCS_FirstBusy) {
+ if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastBusy = NULL;
+ } else {
+ pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+ if (pTmpScb == pCurHcb->HCS_LastBusy)
+ pCurHcb->HCS_LastBusy = pPrevScb;
+ }
+ pTmpScb->SCB_NxtScb = NULL;
+
+
+ pTmpScb->SCB_HaStat = HOST_ABORTED;
+ pTmpScb->SCB_Flags |= SCF_DONE;
+ if (pTmpScb->SCB_Flags & SCF_POST)
+ (*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_ABORT_SUCCESS;
+ }
+ }
+ pPrevScb = pTmpScb;
+ pTmpScb = pTmpScb->SCB_NxtScb;
+ }
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return (SCSI_ABORT_NOT_RUNNING);
+}
+
+/***************************************************************************/
+int tul_bad_seq(HCS * pCurHcb)
+{
+ SCB *pCurScb;
+
+ printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
+
+ if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
+ tul_unlink_busy_scb(pCurHcb, pCurScb);
+ pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+ pCurScb->SCB_TaStat = 0;
+ tul_append_done_scb(pCurHcb, pCurScb);
+ }
+ tul_stop_bm(pCurHcb);
+
+ tul_reset_scsi(pCurHcb, 8); /* 7/29/98 */
+
+ return (tul_post_scsi_rst(pCurHcb));
+}
+
+/************************************************************************/
+int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags)
+{
+ ULONG flags;
+ SCB *pScb;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+
+ if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
+
+ if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+ /* disable Jasmin SCSI Int */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ tulip_main(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ pCurHcb->HCS_Semaph = 1;
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+
+ return SCSI_RESET_SNOOZE;
+ }
+ pScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */
+ while (pScb != NULL) {
+ if (pScb->SCB_Srb == (unsigned char *) pSrb)
+ break;
+ pScb = pScb->SCB_NxtScb;
+ }
+ if (pScb == NULL) {
+ printk("Unable to Reset - No SCB Found\n");
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_RESET_NOT_RUNNING;
+ }
+ }
+ if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_RESET_NOT_RUNNING;
+ }
+ pScb->SCB_Opcode = BusDevRst;
+ pScb->SCB_Flags = SCF_POST;
+ pScb->SCB_Target = target;
+ pScb->SCB_Mode = 0;
+
+ pScb->SCB_Srb = 0;
+ if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
+ pScb->SCB_Srb = (unsigned char *) pSrb;
+ }
+ tul_push_pend_scb(pCurHcb, pScb); /* push this SCB to Pending queue */
+
+ if (pCurHcb->HCS_Semaph == 1) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+ /* disable Jasmin SCSI Int */
+ pCurHcb->HCS_Semaph = 0;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ tulip_main(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ pCurHcb->HCS_Semaph = 1;
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+ }
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return SCSI_RESET_PENDING;
+}
+
+int tul_reset_scsi_bus(HCS * pCurHcb)
+{
+ ULONG flags;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+ pCurHcb->HCS_Semaph = 0;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+
+ tul_stop_bm(pCurHcb);
+
+ tul_reset_scsi(pCurHcb, 2); /* 7/29/98 */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+ tul_post_scsi_rst(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ tulip_main(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ pCurHcb->HCS_Semaph = 1;
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
+}
+
+/************************************************************************/
+void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
+{
+ ULONG flags;
+
+ pCurScb->SCB_Mode = 0;
+
+ pCurScb->SCB_SGIdx = 0;
+ pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+
+ tul_append_pend_scb(pCurHcb, pCurScb); /* Append this SCB to Pending queue */
+
+/* VVVVV 07/21/98 */
+ if (pCurHcb->HCS_Semaph == 1) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+ /* disable Jasmin SCSI Int */
+ pCurHcb->HCS_Semaph = 0;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ tulip_main(pCurHcb);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#endif
+
+ pCurHcb->HCS_Semaph = 1;
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+ }
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return;
+}
+
+/***************************************************************************/
+int tul_isr(HCS * pCurHcb)
+{
+ /* Enter critical section */
+
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
+ if (pCurHcb->HCS_Semaph == 1) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+ /* Disable Tulip SCSI Int */
+ pCurHcb->HCS_Semaph = 0;
+
+ tulip_main(pCurHcb);
+
+ pCurHcb->HCS_Semaph = 1;
+ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+/***************************************************************************/
+int tulip_main(HCS * pCurHcb)
+{
+ SCB *pCurScb;
+
+ for (;;) {
+
+ tulip_scsi(pCurHcb); /* Call tulip_scsi */
+
+ while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) { /* find done entry */
+ if (pCurScb->SCB_TaStat == QUEUE_FULL) {
+ pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
+ pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
+ pCurScb->SCB_TaStat = 0;
+ tul_append_pend_scb(pCurHcb, pCurScb);
+ continue;
+ }
+ if (!(pCurScb->SCB_Mode & SCM_RSENS)) { /* not in auto req. sense mode */
+ if (pCurScb->SCB_TaStat == 2) {
+
+ /* clr sync. nego flag */
+
+ if (pCurScb->SCB_Flags & SCF_SENSE) {
+ BYTE len;
+ len = pCurScb->SCB_SenseLen;
+ if (len == 0)
+ len = 1;
+ pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
+ pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
+ pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR); /* for xfer_data_in */
+/* pCurScb->SCB_Flags |= SCF_NO_DCHK; */
+ /* so, we won't report worng direction in xfer_data_in,
+ and won't report HOST_DO_DU in state_6 */
+ pCurScb->SCB_Mode = SCM_RSENS;
+ pCurScb->SCB_Ident &= 0xBF; /* Disable Disconnect */
+ pCurScb->SCB_TagMsg = 0;
+ pCurScb->SCB_TaStat = 0;
+ pCurScb->SCB_CDBLen = 6;
+ pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
+ pCurScb->SCB_CDB[1] = 0;
+ pCurScb->SCB_CDB[2] = 0;
+ pCurScb->SCB_CDB[3] = 0;
+ pCurScb->SCB_CDB[4] = len;
+ pCurScb->SCB_CDB[5] = 0;
+ tul_push_pend_scb(pCurHcb, pCurScb);
+ break;
+ }
+ }
+ } else { /* in request sense mode */
+
+ if (pCurScb->SCB_TaStat == 2) { /* check contition status again after sending
+ requset sense cmd 0x3 */
+ pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+ }
+ pCurScb->SCB_TaStat = 2;
+ }
+ pCurScb->SCB_Flags |= SCF_DONE;
+ if (pCurScb->SCB_Flags & SCF_POST) {
+ (*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
+ }
+ } /* while */
+
+ /* find_active: */
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
+ continue;
+
+ if (pCurHcb->HCS_ActScb) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */
+ return 1; /* return to OS, enable interrupt */
+ }
+ /* Check pending SCB */
+ if (tul_find_first_pend_scb(pCurHcb) == NULL) {
+ return 1; /* return to OS, enable interrupt */
+ }
+ } /* End of for loop */
+ /* statement won't reach here */
+}
+
+
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+
+/***************************************************************************/
+void tulip_scsi(HCS * pCurHcb)
+{
+ SCB *pCurScb;
+ TCS *pCurTcb;
+
+ /* make sure to service interrupt asap */
+
+ if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
+
+ pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
+ pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
+ pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+ if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* SCSI bus reset detected */
+ int_tul_scsi_rst(pCurHcb);
+ return;
+ }
+ if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if selected/reselected interrupt */
+ if (int_tul_resel(pCurHcb) == 0)
+ tul_next_state(pCurHcb);
+ return;
+ }
+ if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
+ int_tul_busfree(pCurHcb);
+ return;
+ }
+ if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */
+ int_tul_busfree(pCurHcb); /* unexpected bus free or sel timeout */
+ return;
+ }
+ if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) { /* func complete or Bus service */
+ if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
+ tul_next_state(pCurHcb);
+ return;
+ }
+ }
+ if (pCurHcb->HCS_ActScb != NULL)
+ return;
+
+ if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
+ return;
+
+ /* program HBA's SCSI ID & target SCSI ID */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
+ (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
+ if (pCurScb->SCB_Opcode == ExecSCSI) {
+ pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+
+ if (pCurScb->SCB_TagMsg)
+ pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
+ else
+ pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
+ if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) { /* do wdtr negotiation */
+ tul_select_atn_stop(pCurHcb, pCurScb);
+ } else {
+ if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync negotiation */
+ tul_select_atn_stop(pCurHcb, pCurScb);
+ } else {
+ if (pCurScb->SCB_TagMsg)
+ tul_select_atn3(pCurHcb, pCurScb);
+ else
+ tul_select_atn(pCurHcb, pCurScb);
+ }
+ }
+ if (pCurScb->SCB_Flags & SCF_POLL) {
+ while (wait_tulip(pCurHcb) != -1) {
+ if (tul_next_state(pCurHcb) == -1)
+ break;
+ }
+ }
+ } else if (pCurScb->SCB_Opcode == BusDevRst) {
+ tul_select_atn_stop(pCurHcb, pCurScb);
+ pCurScb->SCB_NxtStat = 8;
+ if (pCurScb->SCB_Flags & SCF_POLL) {
+ while (wait_tulip(pCurHcb) != -1) {
+ if (tul_next_state(pCurHcb) == -1)
+ break;
+ }
+ }
+ } else if (pCurScb->SCB_Opcode == AbortCmd) {
+ ULONG srbp;
+
+ srbp = (ULONG) pCurScb->SCB_Srb;
+/* 08/03/98 */
+ if (tul_abort_srb(pCurHcb, srbp) != 0) {
+
+
+ tul_unlink_pend_scb(pCurHcb, pCurScb);
+
+ tul_release_scb(pCurHcb, pCurScb);
+ } else {
+ pCurScb->SCB_Opcode = BusDevRst;
+ tul_select_atn_stop(pCurHcb, pCurScb);
+ pCurScb->SCB_NxtStat = 8;
+ }
+
+/* 08/03/98 */
+ } else {
+ tul_unlink_pend_scb(pCurHcb, pCurScb);
+ pCurScb->SCB_HaStat = 0x16; /* bad command */
+ tul_append_done_scb(pCurHcb, pCurScb);
+ }
+ return;
+}
+
+
+/***************************************************************************/
+int tul_next_state(HCS * pCurHcb)
+{
+ int next;
+
+ next = pCurHcb->HCS_ActScb->SCB_NxtStat;
+ for (;;) {
+ switch (next) {
+ case 1:
+ next = tul_state_1(pCurHcb);
+ break;
+ case 2:
+ next = tul_state_2(pCurHcb);
+ break;
+ case 3:
+ next = tul_state_3(pCurHcb);
+ break;
+ case 4:
+ next = tul_state_4(pCurHcb);
+ break;
+ case 5:
+ next = tul_state_5(pCurHcb);
+ break;
+ case 6:
+ next = tul_state_6(pCurHcb);
+ break;
+ case 7:
+ next = tul_state_7(pCurHcb);
+ break;
+ case 8:
+ return (tul_bus_device_reset(pCurHcb));
+ default:
+ return (tul_bad_seq(pCurHcb));
+ }
+ if (next <= 0)
+ return next;
+ }
+}
+
+
+/***************************************************************************/
+/* sTate after selection with attention & stop */
+int tul_state_1(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+#if DEBUG_STATE
+ printk("-s1-");
+#endif
+
+ tul_unlink_pend_scb(pCurHcb, pCurScb);
+ tul_append_busy_scb(pCurHcb, pCurScb);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+ /* ATN on */
+ if (pCurHcb->HCS_Phase == MSG_OUT) {
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
+
+ if (pCurScb->SCB_TagMsg) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+ }
+ if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
+
+ pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2); /* Extended msg length */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* Sync request */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* Start from 16 bits */
+ } else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
+
+ pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* extended msg length */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
+ return (3);
+}
+
+
+/***************************************************************************/
+/* state after selection with attention */
+/* state after selection with attention3 */
+int tul_state_2(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+#if DEBUG_STATE
+ printk("-s2-");
+#endif
+
+ tul_unlink_pend_scb(pCurHcb, pCurScb);
+ tul_append_busy_scb(pCurHcb, pCurScb);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+
+ if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
+ return (4);
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
+ return (3);
+}
+
+/***************************************************************************/
+/* state before CDB xfer is done */
+int tul_state_3(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+ int i;
+
+#if DEBUG_STATE
+ printk("-s3-");
+#endif
+ for (;;) {
+ switch (pCurHcb->HCS_Phase) {
+ case CMD_OUT: /* Command out phase */
+ for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+ if (pCurHcb->HCS_Phase == CMD_OUT) {
+ return (tul_bad_seq(pCurHcb));
+ }
+ return (4);
+
+ case MSG_IN: /* Message in phase */
+ pCurScb->SCB_NxtStat = 3;
+ if (tul_msgin(pCurHcb) == -1)
+ return (-1);
+ break;
+
+ case STATUS_IN: /* Status phase */
+ if (tul_status_msg(pCurHcb) == -1)
+ return (-1);
+ break;
+
+ case MSG_OUT: /* Message out phase */
+ if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+
+ } else {
+ pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3); /* ext. msg len */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1); /* sync request */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET); /* REQ/ACK offset */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
+
+ }
+ break;
+
+ default:
+ return (tul_bad_seq(pCurHcb));
+ }
+ }
+}
+
+
+/***************************************************************************/
+int tul_state_4(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+#if DEBUG_STATE
+ printk("-s4-");
+#endif
+ if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
+ return (6); /* Go to state 6 */
+ }
+ for (;;) {
+ if (pCurScb->SCB_BufLen == 0)
+ return (6); /* Go to state 6 */
+
+ switch (pCurHcb->HCS_Phase) {
+
+ case STATUS_IN: /* Status phase */
+ if ((pCurScb->SCB_Flags & SCF_DIR) != 0) { /* if direction bit set then report data underrun */
+ pCurScb->SCB_HaStat = HOST_DO_DU;
+ }
+ if ((tul_status_msg(pCurHcb)) == -1)
+ return (-1);
+ break;
+
+ case MSG_IN: /* Message in phase */
+ pCurScb->SCB_NxtStat = 0x4;
+ if (tul_msgin(pCurHcb) == -1)
+ return (-1);
+ break;
+
+ case MSG_OUT: /* Message out phase */
+ if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
+ pCurScb->SCB_BufLen = 0;
+ pCurScb->SCB_HaStat = HOST_DO_DU;
+ if (tul_msgout_ide(pCurHcb) == -1)
+ return (-1);
+ return (6); /* Go to state 6 */
+ } else {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+ }
+ break;
+
+ case DATA_IN: /* Data in phase */
+ return (tul_xfer_data_in(pCurHcb));
+
+ case DATA_OUT: /* Data out phase */
+ return (tul_xfer_data_out(pCurHcb));
+
+ default:
+ return (tul_bad_seq(pCurHcb));
+ }
+ }
+}
+
+
+/***************************************************************************/
+/* state after dma xfer done or phase change before xfer done */
+int tul_state_5(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ long cnt, xcnt; /* cannot use unsigned !! code: if (xcnt < 0) */
+
+#if DEBUG_STATE
+ printk("-s5-");
+#endif
+/*------ get remaining count -------*/
+
+ cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
+
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
+ /* ----------------------- DATA_IN ----------------------------- */
+ /* check scsi parity error */
+ if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
+ pCurScb->SCB_HaStat = HOST_DO_DU;
+ }
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* DMA xfer pending, Send STOP */
+ /* tell Hardware scsi xfer has been terminated */
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
+ /* wait until DMA xfer not pending */
+ while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
+ }
+ } else {
+/*-------- DATA OUT -----------*/
+ if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
+ if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
+ cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
+ else
+ cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
+ }
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
+ /* wait Abort DMA xfer done */
+ while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+ }
+ if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1) {
+ return (-1);
+ }
+ cnt = 0;
+ } else {
+ if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ }
+ }
+
+ if (cnt == 0) {
+ pCurScb->SCB_BufLen = 0;
+ return (6); /* Go to state 6 */
+ }
+ /* Update active data pointer */
+ xcnt = (long) pCurScb->SCB_BufLen - cnt; /* xcnt== bytes already xferred */
+ pCurScb->SCB_BufLen = (U32) cnt; /* cnt == bytes left to be xferred */
+ if (pCurScb->SCB_Flags & SCF_SG) {
+ register SG *sgp;
+ ULONG i;
+
+ sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
+ for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
+ xcnt -= (long) sgp->SG_Len;
+ if (xcnt < 0) { /* this sgp xfer half done */
+ xcnt += (long) sgp->SG_Len; /* xcnt == bytes xferred in this sgp */
+ sgp->SG_Ptr += (U32) xcnt; /* new ptr to be xfer */
+ sgp->SG_Len -= (U32) xcnt; /* new len to be xfer */
+ pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
+ /* new SG table ptr */
+ pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
+ /* new SG table len */
+ pCurScb->SCB_SGIdx = (WORD) i;
+ /* for next disc and come in this loop */
+ return (4); /* Go to state 4 */
+ }
+ /* else (xcnt >= 0 , i.e. this sgp already xferred */
+ } /* for */
+ return (6); /* Go to state 6 */
+ } else {
+ pCurScb->SCB_BufPtr += (U32) xcnt;
+ }
+ return (4); /* Go to state 4 */
+}
+
+/***************************************************************************/
+/* state after Data phase */
+int tul_state_6(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+#if DEBUG_STATE
+ printk("-s6-");
+#endif
+ for (;;) {
+ switch (pCurHcb->HCS_Phase) {
+ case STATUS_IN: /* Status phase */
+ if ((tul_status_msg(pCurHcb)) == -1)
+ return (-1);
+ break;
+
+ case MSG_IN: /* Message in phase */
+ pCurScb->SCB_NxtStat = 6;
+ if ((tul_msgin(pCurHcb)) == -1)
+ return (-1);
+ break;
+
+ case MSG_OUT: /* Message out phase */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP); /* msg nop */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+ break;
+
+ case DATA_IN: /* Data in phase */
+ return (tul_xpad_in(pCurHcb));
+
+ case DATA_OUT: /* Data out phase */
+ return (tul_xpad_out(pCurHcb));
+
+ default:
+ return (tul_bad_seq(pCurHcb));
+ }
+ }
+}
+
+/***************************************************************************/
+int tul_state_7(HCS * pCurHcb)
+{
+ int cnt, i;
+
+#if DEBUG_STATE
+ printk("-s7-");
+#endif
+ /* flush SCSI FIFO */
+ cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
+ if (cnt) {
+ for (i = 0; i < cnt; i++)
+ TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+ }
+ switch (pCurHcb->HCS_Phase) {
+ case DATA_IN: /* Data in phase */
+ case DATA_OUT: /* Data out phase */
+ return (tul_bad_seq(pCurHcb));
+ default:
+ return (6); /* Go to state 6 */
+ }
+}
+
+/***************************************************************************/
+int tul_xfer_data_in(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+ if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
+ return (6); /* wrong direction */
+ }
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN); /* 7/25/95 */
+
+ if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
+ } else {
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
+ }
+ pCurScb->SCB_NxtStat = 0x5;
+ return (0); /* return to OS, wait xfer done , let jas_isr come in */
+}
+
+
+/***************************************************************************/
+int tul_xfer_data_out(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+ if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
+ return (6); /* wrong direction */
+ }
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
+
+ if (pCurScb->SCB_Flags & SCF_SG) { /* S/G xfer */
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
+ } else {
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
+ }
+
+ pCurScb->SCB_NxtStat = 0x5;
+ return (0); /* return to OS, wait xfer done , let jas_isr come in */
+}
+
+
+/***************************************************************************/
+int tul_xpad_in(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+
+ if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
+ pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */
+ }
+ for (;;) {
+ if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+ else
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if ((wait_tulip(pCurHcb)) == -1) {
+ return (-1);
+ }
+ if (pCurHcb->HCS_Phase != DATA_IN) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ return (6);
+ }
+ TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+ }
+}
+
+int tul_xpad_out(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+
+ if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
+ pCurScb->SCB_HaStat = HOST_DO_DU; /* over run */
+ }
+ for (;;) {
+ if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+ else
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ if ((wait_tulip(pCurHcb)) == -1) {
+ return (-1);
+ }
+ if (pCurHcb->HCS_Phase != DATA_OUT) { /* Disable wide CPU to allow read 16 bits */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ return (6);
+ }
+ }
+}
+
+
+/***************************************************************************/
+int tul_status_msg(HCS * pCurHcb)
+{ /* status & MSG_IN */
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ BYTE msg;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
+ if ((wait_tulip(pCurHcb)) == -1) {
+ return (-1);
+ }
+ /* get status */
+ pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+
+ if (pCurHcb->HCS_Phase == MSG_OUT) {
+ if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
+ } else {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ return (wait_tulip(pCurHcb));
+ }
+ if (pCurHcb->HCS_Phase == MSG_IN) {
+ msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+ if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) { /* Parity error */
+ if ((tul_msgin_accept(pCurHcb)) == -1)
+ return (-1);
+ if (pCurHcb->HCS_Phase != MSG_OUT)
+ return (tul_bad_seq(pCurHcb));
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ return (wait_tulip(pCurHcb));
+ }
+ if (msg == 0) { /* Command complete */
+
+ if ((pCurScb->SCB_TaStat & 0x18) == 0x10) { /* No link support */
+ return (tul_bad_seq(pCurHcb));
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+ return tul_wait_done_disc(pCurHcb);
+
+ }
+ if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
+ if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
+ return (tul_msgin_accept(pCurHcb));
+ }
+ }
+ return (tul_bad_seq(pCurHcb));
+}
+
+
+/***************************************************************************/
+/* scsi bus free */
+int int_tul_busfree(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+ if (pCurScb != NULL) {
+ if (pCurScb->SCB_Status & SCB_SELECT) { /* selection timeout */
+ tul_unlink_pend_scb(pCurHcb, pCurScb);
+ pCurScb->SCB_HaStat = HOST_SEL_TOUT;
+ tul_append_done_scb(pCurHcb, pCurScb);
+ } else { /* Unexpected bus free */
+ tul_unlink_busy_scb(pCurHcb, pCurScb);
+ pCurScb->SCB_HaStat = HOST_BUS_FREE;
+ tul_append_done_scb(pCurHcb, pCurScb);
+ }
+ pCurHcb->HCS_ActScb = NULL;
+ pCurHcb->HCS_ActTcs = NULL;
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */
+ return (-1);
+}
+
+
+/***************************************************************************/
+/* scsi bus reset */
+int int_tul_scsi_rst(HCS * pCurHcb)
+{
+ SCB *pCurScb;
+ int i;
+
+ /* if DMA xfer is pending, abort DMA xfer */
+ if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+ /* wait Abort DMA xfer done */
+ while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ }
+ /* Abort all active & disconnected scb */
+ while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
+ pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+ tul_append_done_scb(pCurHcb, pCurScb);
+ }
+ pCurHcb->HCS_ActScb = NULL;
+ pCurHcb->HCS_ActTcs = NULL;
+
+ /* clr sync nego. done flag */
+ for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
+ pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+ }
+ return (-1);
+}
+
+
+/***************************************************************************/
+/* scsi reselection */
+int int_tul_resel(HCS * pCurHcb)
+{
+ SCB *pCurScb;
+ TCS *pCurTcb;
+ BYTE tag, msg = 0;
+ BYTE tar, lun;
+
+ if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
+ if (pCurScb->SCB_Status & SCB_SELECT) { /* if waiting for selection complete */
+ pCurScb->SCB_Status &= ~SCB_SELECT;
+ }
+ pCurHcb->HCS_ActScb = NULL;
+ }
+ /* --------- get target id---------------------- */
+ tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
+ /* ------ get LUN from Identify message----------- */
+ lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
+ /* 07/22/98 from 0x1F -> 0x0F */
+ pCurTcb = &pCurHcb->HCS_Tcs[tar];
+ pCurHcb->HCS_ActTcs = pCurTcb;
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
+
+
+ /* ------------- tag queueing ? ------------------- */
+ if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
+ if ((tul_msgin_accept(pCurHcb)) == -1)
+ return (-1);
+ if (pCurHcb->HCS_Phase != MSG_IN)
+ goto no_tag;
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if ((wait_tulip(pCurHcb)) == -1)
+ return (-1);
+ msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag Message */
+
+ if ((msg < MSG_STAG) || (msg > MSG_OTAG)) /* Is simple Tag */
+ goto no_tag;
+
+ if ((tul_msgin_accept(pCurHcb)) == -1)
+ return (-1);
+
+ if (pCurHcb->HCS_Phase != MSG_IN)
+ goto no_tag;
+
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if ((wait_tulip(pCurHcb)) == -1)
+ return (-1);
+ tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* Read Tag ID */
+ pCurScb = pCurHcb->HCS_Scb + tag;
+ if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
+ return tul_msgout_abort_tag(pCurHcb);
+ }
+ if (pCurScb->SCB_Status != SCB_BUSY) { /* 03/24/95 */
+ return tul_msgout_abort_tag(pCurHcb);
+ }
+ pCurHcb->HCS_ActScb = pCurScb;
+ if ((tul_msgin_accept(pCurHcb)) == -1)
+ return (-1);
+ } else { /* No tag */
+ no_tag:
+ if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
+ return tul_msgout_abort_targ(pCurHcb);
+ }
+ pCurHcb->HCS_ActScb = pCurScb;
+ if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
+ if ((tul_msgin_accept(pCurHcb)) == -1)
+ return (-1);
+ }
+ }
+ return 0;
+}
+
+
+/***************************************************************************/
+int int_tul_bad_seq(HCS * pCurHcb)
+{ /* target wrong phase */
+ SCB *pCurScb;
+ int i;
+
+ tul_reset_scsi(pCurHcb, 10);
+
+ while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
+ pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+ tul_append_done_scb(pCurHcb, pCurScb);
+ }
+ for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
+ pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);;
+ }
+ return (-1);
+}
+
+
+/***************************************************************************/
+int tul_msgout_abort_targ(HCS * pCurHcb)
+{
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+ if (tul_msgin_accept(pCurHcb) == -1)
+ return (-1);
+ if (pCurHcb->HCS_Phase != MSG_OUT)
+ return (tul_bad_seq(pCurHcb));
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+
+ return tul_wait_disc(pCurHcb);
+}
+
+/***************************************************************************/
+int tul_msgout_abort_tag(HCS * pCurHcb)
+{
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+ if (tul_msgin_accept(pCurHcb) == -1)
+ return (-1);
+ if (pCurHcb->HCS_Phase != MSG_OUT)
+ return (tul_bad_seq(pCurHcb));
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+
+ return tul_wait_disc(pCurHcb);
+
+}
+
+/***************************************************************************/
+int tul_msgin(HCS * pCurHcb)
+{
+ TCS *pCurTcb;
+
+ for (;;) {
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if ((wait_tulip(pCurHcb)) == -1)
+ return (-1);
+
+ switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
+ case MSG_DISC: /* Disconnect msg */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+
+ return tul_wait_disc(pCurHcb);
+
+ case MSG_SDP:
+ case MSG_RESTORE:
+ case MSG_NOP:
+ tul_msgin_accept(pCurHcb);
+ break;
+
+ case MSG_REJ: /* Clear ATN first */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
+ (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
+ pCurTcb = pCurHcb->HCS_ActTcs;
+ if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) { /* do sync nego */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+ }
+ tul_msgin_accept(pCurHcb);
+ break;
+
+ case MSG_EXTEND: /* extended msg */
+ tul_msgin_extend(pCurHcb);
+ break;
+
+ case MSG_IGNOREWIDE:
+ tul_msgin_accept(pCurHcb);
+ break;
+
+ /* get */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if (wait_tulip(pCurHcb) == -1)
+ return -1;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0); /* put pad */
+ TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get IGNORE field */
+ TUL_RD(pCurHcb->HCS_Base, TUL_SFifo); /* get pad */
+
+ tul_msgin_accept(pCurHcb);
+ break;
+
+ case MSG_COMP:
+ {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+ return tul_wait_done_disc(pCurHcb);
+ }
+ default:
+ tul_msgout_reject(pCurHcb);
+ break;
+ }
+ if (pCurHcb->HCS_Phase != MSG_IN)
+ return (pCurHcb->HCS_Phase);
+ }
+ /* statement won't reach here */
+}
+
+
+
+
+/***************************************************************************/
+int tul_msgout_reject(HCS * pCurHcb)
+{
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+
+ if ((tul_msgin_accept(pCurHcb)) == -1)
+ return (-1);
+
+ if (pCurHcb->HCS_Phase == MSG_OUT) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ); /* Msg reject */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ return (wait_tulip(pCurHcb));
+ }
+ return (pCurHcb->HCS_Phase);
+}
+
+
+
+/***************************************************************************/
+int tul_msgout_ide(HCS * pCurHcb)
+{
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE); /* Initiator Detected Error */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ return (wait_tulip(pCurHcb));
+}
+
+
+/***************************************************************************/
+int tul_msgin_extend(HCS * pCurHcb)
+{
+ BYTE len, idx;
+
+ if (tul_msgin_accept(pCurHcb) != MSG_IN)
+ return (pCurHcb->HCS_Phase);
+
+ /* Get extended msg length */
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+
+ len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+ pCurHcb->HCS_Msg[0] = len;
+ for (idx = 1; len != 0; len--) {
+
+ if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
+ return (pCurHcb->HCS_Phase);
+ TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+ if (wait_tulip(pCurHcb) == -1)
+ return (-1);
+ pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+ }
+ if (pCurHcb->HCS_Msg[1] == 1) { /* if it's synchronous data transfer request */
+ if (pCurHcb->HCS_Msg[0] != 3) /* if length is not right */
+ return (tul_msgout_reject(pCurHcb));
+ if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) { /* Set OFFSET=0 to do async, nego back */
+ pCurHcb->HCS_Msg[3] = 0;
+ } else {
+ if ((tul_msgin_sync(pCurHcb) == 0) &&
+ (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
+ tul_sync_done(pCurHcb);
+ return (tul_msgin_accept(pCurHcb));
+ }
+ }
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+ if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
+ return (pCurHcb->HCS_Phase);
+ /* sync msg out */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+
+ tul_sync_done(pCurHcb);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ return (wait_tulip(pCurHcb));
+ }
+ if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
+ return (tul_msgout_reject(pCurHcb));
+ /* if it's WIDE DATA XFER REQ */
+ if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
+ pCurHcb->HCS_Msg[2] = 0;
+ } else {
+ if (pCurHcb->HCS_Msg[2] > 2) /* > 32 bits */
+ return (tul_msgout_reject(pCurHcb));
+ if (pCurHcb->HCS_Msg[2] == 2) { /* == 32 */
+ pCurHcb->HCS_Msg[2] = 1;
+ } else {
+ if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
+ wdtr_done(pCurHcb);
+ if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+ return (tul_msgin_accept(pCurHcb));
+ }
+ }
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+
+ if (tul_msgin_accept(pCurHcb) != MSG_OUT)
+ return (pCurHcb->HCS_Phase);
+ /* WDTR msg out */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+ return (wait_tulip(pCurHcb));
+}
+
+/***************************************************************************/
+int tul_msgin_sync(HCS * pCurHcb)
+{
+ char default_period;
+
+ default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
+ if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
+ pCurHcb->HCS_Msg[3] = MAX_OFFSET;
+ if (pCurHcb->HCS_Msg[2] < default_period) {
+ pCurHcb->HCS_Msg[2] = default_period;
+ return 1;
+ }
+ if (pCurHcb->HCS_Msg[2] >= 59) { /* Change to async */
+ pCurHcb->HCS_Msg[3] = 0;
+ }
+ return 1;
+ }
+ /* offset requests asynchronous transfers ? */
+ if (pCurHcb->HCS_Msg[3] == 0) {
+ return 0;
+ }
+ if (pCurHcb->HCS_Msg[2] < default_period) {
+ pCurHcb->HCS_Msg[2] = default_period;
+ return 1;
+ }
+ if (pCurHcb->HCS_Msg[2] >= 59) {
+ pCurHcb->HCS_Msg[3] = 0;
+ return 1;
+ }
+ return 0;
+}
+
+
+/***************************************************************************/
+int wdtr_done(HCS * pCurHcb)
+{
+ pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
+ pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
+
+ pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
+ if (pCurHcb->HCS_Msg[2]) { /* if 16 bit */
+ pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
+ }
+ pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+
+ return 1;
+}
+
+/***************************************************************************/
+int tul_sync_done(HCS * pCurHcb)
+{
+ int i;
+
+ pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
+
+ if (pCurHcb->HCS_Msg[3]) {
+ pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
+ for (i = 0; i < 8; i++) {
+ if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2]) /* pick the big one */
+ break;
+ }
+ pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
+ pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
+ }
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+
+ return (-1);
+}
+
+
+int tul_post_scsi_rst(HCS * pCurHcb)
+{
+ SCB *pCurScb;
+ TCS *pCurTcb;
+ int i;
+
+ pCurHcb->HCS_ActScb = 0;
+ pCurHcb->HCS_ActTcs = 0;
+ pCurHcb->HCS_Flags = 0;
+
+ while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
+ pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+ tul_append_done_scb(pCurHcb, pCurScb);
+ }
+ /* clear sync done flag */
+ pCurTcb = &pCurHcb->HCS_Tcs[0];
+ for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
+ pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+ /* Initialize the sync. xfer register values to an asyn xfer */
+ pCurTcb->TCS_JS_Period = 0;
+ pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
+ pCurHcb->HCS_ActTags[0] = 0; /* 07/22/98 */
+ pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; /* 07/22/98 */
+ } /* for */
+
+ return (-1);
+}
+
+/***************************************************************************/
+void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
+{
+ pCurScb->SCB_Status |= SCB_SELECT;
+ pCurScb->SCB_NxtStat = 0x1;
+ pCurHcb->HCS_ActScb = pCurScb;
+ pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
+ return;
+}
+
+
+/***************************************************************************/
+void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
+{
+ int i;
+
+ pCurScb->SCB_Status |= SCB_SELECT;
+ pCurScb->SCB_NxtStat = 0x2;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
+ for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
+ pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+ pCurHcb->HCS_ActScb = pCurScb;
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
+ return;
+}
+
+/***************************************************************************/
+void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
+{
+ int i;
+
+ pCurScb->SCB_Status |= SCB_SELECT;
+ pCurScb->SCB_NxtStat = 0x2;
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+ for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
+ pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+ pCurHcb->HCS_ActScb = pCurScb;
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
+ return;
+}
+
+/***************************************************************************/
+/* SCSI Bus Device Reset */
+int tul_bus_device_reset(HCS * pCurHcb)
+{
+ SCB *pCurScb = pCurHcb->HCS_ActScb;
+ TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+ SCB *pTmpScb, *pPrevScb;
+ BYTE tar;
+
+ if (pCurHcb->HCS_Phase != MSG_OUT) {
+ return (int_tul_bad_seq(pCurHcb)); /* Unexpected phase */
+ }
+ tul_unlink_pend_scb(pCurHcb, pCurScb);
+ tul_release_scb(pCurHcb, pCurScb);
+
+
+ tar = pCurScb->SCB_Target; /* target */
+ pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
+ /* clr sync. nego & WDTR flags 07/22/98 */
+
+ /* abort all SCB with same target */
+ pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy; /* Check Busy queue */
+ while (pTmpScb != NULL) {
+
+ if (pTmpScb->SCB_Target == tar) {
+ /* unlink it */
+ if (pTmpScb == pCurHcb->HCS_FirstBusy) {
+ if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+ pCurHcb->HCS_LastBusy = NULL;
+ } else {
+ pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+ if (pTmpScb == pCurHcb->HCS_LastBusy)
+ pCurHcb->HCS_LastBusy = pPrevScb;
+ }
+ pTmpScb->SCB_HaStat = HOST_ABORTED;
+ tul_append_done_scb(pCurHcb, pTmpScb);
+ }
+ /* Previous haven't change */
+ else {
+ pPrevScb = pTmpScb;
+ }
+ pTmpScb = pTmpScb->SCB_NxtScb;
+ }
+
+ TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+
+ return tul_wait_disc(pCurHcb);
+
+}
+
+/***************************************************************************/
+int tul_msgin_accept(HCS * pCurHcb)
+{
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+ return (wait_tulip(pCurHcb));
+}
+
+/***************************************************************************/
+int wait_tulip(HCS * pCurHcb)
+{
+
+ while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
+ & TSS_INT_PENDING));
+
+ pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+ pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
+ pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
+
+ if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) { /* if SCSI bus reset detected */
+ return (int_tul_resel(pCurHcb));
+ }
+ if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) { /* if selected/reselected timeout interrupt */
+ return (int_tul_busfree(pCurHcb));
+ }
+ if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */
+ return (int_tul_scsi_rst(pCurHcb));
+ }
+ if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */
+ if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */
+ tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
+ pCurHcb->HCS_ActScb->SCB_HaStat = 0;
+ tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
+ pCurHcb->HCS_ActScb = NULL;
+ pCurHcb->HCS_ActTcs = NULL;
+ pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */
+ return (-1);
+ }
+ if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */
+ pCurHcb->HCS_ActScb = NULL;
+ pCurHcb->HCS_ActTcs = NULL;
+ pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */
+ return (-1);
+ }
+ return (int_tul_busfree(pCurHcb));
+ }
+ if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
+ return (pCurHcb->HCS_Phase);
+ }
+ return (pCurHcb->HCS_Phase);
+}
+/***************************************************************************/
+int tul_wait_disc(HCS * pCurHcb)
+{
+
+ while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
+ & TSS_INT_PENDING));
+
+
+ pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+
+ if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */
+ return (int_tul_scsi_rst(pCurHcb));
+ }
+ if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */
+ pCurHcb->HCS_ActScb = NULL;
+ return (-1);
+ }
+ return (tul_bad_seq(pCurHcb));
+}
+
+/***************************************************************************/
+int tul_wait_done_disc(HCS * pCurHcb)
+{
+
+
+ while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
+ & TSS_INT_PENDING));
+
+ pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+
+
+ if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) { /* if SCSI bus reset detected */
+ return (int_tul_scsi_rst(pCurHcb));
+ }
+ if (pCurHcb->HCS_JSInt & TSS_DISC_INT) { /* BUS disconnection */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO); /* Flush SCSI FIFO */
+ TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); /* Enable HW reselect */
+ tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
+
+ tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
+ pCurHcb->HCS_ActScb = NULL;
+ return (-1);
+ }
+ return (tul_bad_seq(pCurHcb));
+}
+
+/**************************** EOF *********************************/
diff --git a/drivers/scsi/i91uscsi.h b/drivers/scsi/i91uscsi.h
new file mode 100644
index 000000000..b3a2253bd
--- /dev/null
+++ b/drivers/scsi/i91uscsi.h
@@ -0,0 +1,857 @@
+/**************************************************************************
+ * Initio 9100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 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 name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
+ *
+ **************************************************************************/
+
+#include <linux/config.h>
+
+#define ULONG unsigned long
+#define USHORT unsigned short
+#define UCHAR unsigned char
+#define BYTE unsigned char
+#define WORD unsigned short
+#define DWORD unsigned long
+#define UBYTE unsigned char
+#define UWORD unsigned short
+#define UDWORD unsigned long
+#ifdef ALPHA
+#define U32 unsigned int
+#else
+#define U32 unsigned long
+#endif
+
+#ifndef NULL
+#define NULL 0 /* zero */
+#endif
+#ifndef TRUE
+#define TRUE (1) /* boolean true */
+#endif
+#ifndef FALSE
+#define FALSE (0) /* boolean false */
+#endif
+#ifndef FAILURE
+#define FAILURE (-1)
+#endif
+
+#define TOTAL_SG_ENTRY 32
+#define MAX_SUPPORTED_ADAPTERS 8
+#define MAX_OFFSET 15
+#define MAX_TARGETS 16
+
+#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */
+#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */
+#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */
+#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */
+
+#define _I91USCSI_H
+
+typedef struct {
+ unsigned short base;
+ unsigned short vec;
+} i91u_config;
+
+/***************************************/
+/* Tulip Configuration Register Set */
+/***************************************/
+#define TUL_PVID 0x00 /* Vendor ID */
+#define TUL_PDID 0x02 /* Device ID */
+#define TUL_PCMD 0x04 /* Command */
+#define TUL_PSTUS 0x06 /* Status */
+#define TUL_PRID 0x08 /* Revision number */
+#define TUL_PPI 0x09 /* Programming interface */
+#define TUL_PSC 0x0A /* Sub Class */
+#define TUL_PBC 0x0B /* Base Class */
+#define TUL_PCLS 0x0C /* Cache line size */
+#define TUL_PLTR 0x0D /* Latency timer */
+#define TUL_PHDT 0x0E /* Header type */
+#define TUL_PBIST 0x0F /* BIST */
+#define TUL_PBAD 0x10 /* Base address */
+#define TUL_PBAD1 0x14 /* Base address */
+#define TUL_PBAD2 0x18 /* Base address */
+#define TUL_PBAD3 0x1C /* Base address */
+#define TUL_PBAD4 0x20 /* Base address */
+#define TUL_PBAD5 0x24 /* Base address */
+#define TUL_PRSVD 0x28 /* Reserved */
+#define TUL_PRSVD1 0x2C /* Reserved */
+#define TUL_PRAD 0x30 /* Expansion ROM base address */
+#define TUL_PRSVD2 0x34 /* Reserved */
+#define TUL_PRSVD3 0x38 /* Reserved */
+#define TUL_PINTL 0x3C /* Interrupt line */
+#define TUL_PINTP 0x3D /* Interrupt pin */
+#define TUL_PIGNT 0x3E /* MIN_GNT */
+#define TUL_PMGNT 0x3F /* MAX_GNT */
+
+/************************/
+/* Jasmin Register Set */
+/************************/
+#define TUL_HACFG0 0x40 /* H/A Configuration Register 0 */
+#define TUL_HACFG1 0x41 /* H/A Configuration Register 1 */
+#define TUL_HACFG2 0x42 /* H/A Configuration Register 2 */
+
+#define TUL_SDCFG0 0x44 /* SCSI Device Configuration 0 */
+#define TUL_SDCFG1 0x45 /* SCSI Device Configuration 1 */
+#define TUL_SDCFG2 0x46 /* SCSI Device Configuration 2 */
+#define TUL_SDCFG3 0x47 /* SCSI Device Configuration 3 */
+
+#define TUL_GINTS 0x50 /* Global Interrupt Status Register */
+#define TUL_GIMSK 0x52 /* Global Interrupt MASK Register */
+#define TUL_GCTRL 0x54 /* Global Control Register */
+#define TUL_GCTRL_EEPROM_BIT 0x04
+#define TUL_GCTRL1 0x55 /* Global Control Register */
+#define TUL_DMACFG 0x5B /* DMA configuration */
+#define TUL_NVRAM 0x5D /* Non-volatile RAM port */
+
+#define TUL_SCnt0 0x80 /* 00 R/W Transfer Counter Low */
+#define TUL_SCnt1 0x81 /* 01 R/W Transfer Counter Mid */
+#define TUL_SCnt2 0x82 /* 02 R/W Transfer Count High */
+#define TUL_SFifoCnt 0x83 /* 03 R FIFO counter */
+#define TUL_SIntEnable 0x84 /* 03 W Interrupt enble */
+#define TUL_SInt 0x84 /* 04 R Interrupt Register */
+#define TUL_SCtrl0 0x85 /* 05 W Control 0 */
+#define TUL_SStatus0 0x85 /* 05 R Status 0 */
+#define TUL_SCtrl1 0x86 /* 06 W Control 1 */
+#define TUL_SStatus1 0x86 /* 06 R Status 1 */
+#define TUL_SConfig 0x87 /* 07 W Configuration */
+#define TUL_SStatus2 0x87 /* 07 R Status 2 */
+#define TUL_SPeriod 0x88 /* 08 W Sync. Transfer Period & Offset */
+#define TUL_SOffset 0x88 /* 08 R Offset */
+#define TUL_SScsiId 0x89 /* 09 W SCSI ID */
+#define TUL_SBusId 0x89 /* 09 R SCSI BUS ID */
+#define TUL_STimeOut 0x8A /* 0A W Sel/Resel Time Out Register */
+#define TUL_SIdent 0x8A /* 0A R Identify Message Register */
+#define TUL_SAvail 0x8A /* 0A R Availiable Counter Register */
+#define TUL_SData 0x8B /* 0B R/W SCSI data in/out */
+#define TUL_SFifo 0x8C /* 0C R/W FIFO */
+#define TUL_SSignal 0x90 /* 10 R/W SCSI signal in/out */
+#define TUL_SCmd 0x91 /* 11 R/W Command */
+#define TUL_STest0 0x92 /* 12 R/W Test0 */
+#define TUL_STest1 0x93 /* 13 R/W Test1 */
+#define TUL_SCFG1 0x94 /* 14 R/W Configuration */
+
+#define TUL_XAddH 0xC0 /*DMA Transfer Physical Address */
+#define TUL_XAddW 0xC8 /*DMA Current Transfer Physical Address */
+#define TUL_XCntH 0xD0 /*DMA Transfer Counter */
+#define TUL_XCntW 0xD4 /*DMA Current Transfer Counter */
+#define TUL_XCmd 0xD8 /*DMA Command Register */
+#define TUL_Int 0xDC /*Interrupt Register */
+#define TUL_XStatus 0xDD /*DMA status Register */
+#define TUL_Mask 0xE0 /*Interrupt Mask Register */
+#define TUL_XCtrl 0xE4 /*DMA Control Register */
+#define TUL_XCtrl1 0xE5 /*DMA Control Register 1 */
+#define TUL_XFifo 0xE8 /*DMA FIFO */
+
+#define TUL_WCtrl 0xF7 /*Bus master wait state control */
+#define TUL_DCtrl 0xFB /*DMA delay control */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Command register of Configuration Space Header */
+/*----------------------------------------------------------------------*/
+#define BUSMS 0x04 /* BUS MASTER Enable */
+#define IOSPA 0x01 /* IO Space Enable */
+
+/*----------------------------------------------------------------------*/
+/* Command Codes of Tulip SCSI Command register */
+/*----------------------------------------------------------------------*/
+#define TSC_EN_RESEL 0x80 /* Enable Reselection */
+#define TSC_CMD_COMP 0x84 /* Command Complete Sequence */
+#define TSC_SEL 0x01 /* Select Without ATN Sequence */
+#define TSC_SEL_ATN 0x11 /* Select With ATN Sequence */
+#define TSC_SEL_ATN_DMA 0x51 /* Select With ATN Sequence with DMA */
+#define TSC_SEL_ATN3 0x31 /* Select With ATN3 Sequence */
+#define TSC_SEL_ATNSTOP 0x12 /* Select With ATN and Stop Sequence */
+#define TSC_SELATNSTOP 0x1E /* Select With ATN and Stop Sequence */
+
+#define TSC_SEL_ATN_DIRECT_IN 0x95 /* Select With ATN Sequence */
+#define TSC_SEL_ATN_DIRECT_OUT 0x15 /* Select With ATN Sequence */
+#define TSC_SEL_ATN3_DIRECT_IN 0xB5 /* Select With ATN3 Sequence */
+#define TSC_SEL_ATN3_DIRECT_OUT 0x35 /* Select With ATN3 Sequence */
+#define TSC_XF_DMA_OUT_DIRECT 0x06 /* DMA Xfer Infomation out */
+#define TSC_XF_DMA_IN_DIRECT 0x86 /* DMA Xfer Infomation in */
+
+#define TSC_XF_DMA_OUT 0x43 /* DMA Xfer Infomation out */
+#define TSC_XF_DMA_IN 0xC3 /* DMA Xfer Infomation in */
+#define TSC_XF_FIFO_OUT 0x03 /* FIFO Xfer Infomation out */
+#define TSC_XF_FIFO_IN 0x83 /* FIFO Xfer Infomation in */
+
+#define TSC_MSG_ACCEPT 0x0F /* Message Accept */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Control 0 Register */
+/*----------------------------------------------------------------------*/
+#define TSC_RST_SEQ 0x20 /* Reset sequence counter */
+#define TSC_FLUSH_FIFO 0x10 /* Flush FIFO */
+#define TSC_ABT_CMD 0x04 /* Abort command (sequence) */
+#define TSC_RST_CHIP 0x02 /* Reset SCSI Chip */
+#define TSC_RST_BUS 0x01 /* Reset SCSI Bus */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Control 1 Register */
+/*----------------------------------------------------------------------*/
+#define TSC_EN_SCAM 0x80 /* Enable SCAM */
+#define TSC_TIMER 0x40 /* Select timeout unit */
+#define TSC_EN_SCSI2 0x20 /* SCSI-2 mode */
+#define TSC_PWDN 0x10 /* Power down mode */
+#define TSC_WIDE_CPU 0x08 /* Wide CPU */
+#define TSC_HW_RESELECT 0x04 /* Enable HW reselect */
+#define TSC_EN_BUS_OUT 0x02 /* Enable SCSI data bus out latch */
+#define TSC_EN_BUS_IN 0x01 /* Enable SCSI data bus in latch */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Configuration Register */
+/*----------------------------------------------------------------------*/
+#define TSC_EN_LATCH 0x80 /* Enable phase latch */
+#define TSC_INITIATOR 0x40 /* Initiator mode */
+#define TSC_EN_SCSI_PAR 0x20 /* Enable SCSI parity */
+#define TSC_DMA_8BIT 0x10 /* Alternate dma 8-bits mode */
+#define TSC_DMA_16BIT 0x08 /* Alternate dma 16-bits mode */
+#define TSC_EN_WDACK 0x04 /* Enable DACK while wide SCSI xfer */
+#define TSC_ALT_PERIOD 0x02 /* Alternate sync period mode */
+#define TSC_DIS_SCSIRST 0x01 /* Disable SCSI bus reset us */
+
+#define TSC_INITDEFAULT (TSC_INITIATOR | TSC_EN_LATCH | TSC_ALT_PERIOD | TSC_DIS_SCSIRST)
+
+#define TSC_WIDE_SCSI 0x80 /* Enable Wide SCSI */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI signal Register */
+/*----------------------------------------------------------------------*/
+#define TSC_RST_ACK 0x00 /* Release ACK signal */
+#define TSC_RST_ATN 0x00 /* Release ATN signal */
+#define TSC_RST_BSY 0x00 /* Release BSY signal */
+
+#define TSC_SET_ACK 0x40 /* ACK signal */
+#define TSC_SET_ATN 0x08 /* ATN signal */
+
+#define TSC_REQI 0x80 /* REQ signal */
+#define TSC_ACKI 0x40 /* ACK signal */
+#define TSC_BSYI 0x20 /* BSY signal */
+#define TSC_SELI 0x10 /* SEL signal */
+#define TSC_ATNI 0x08 /* ATN signal */
+#define TSC_MSGI 0x04 /* MSG signal */
+#define TSC_CDI 0x02 /* C/D signal */
+#define TSC_IOI 0x01 /* I/O signal */
+
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Status 0 Register */
+/*----------------------------------------------------------------------*/
+#define TSS_INT_PENDING 0x80 /* Interrupt pending */
+#define TSS_SEQ_ACTIVE 0x40 /* Sequencer active */
+#define TSS_XFER_CNT 0x20 /* Transfer counter zero */
+#define TSS_FIFO_EMPTY 0x10 /* FIFO empty */
+#define TSS_PAR_ERROR 0x08 /* SCSI parity error */
+#define TSS_PH_MASK 0x07 /* SCSI phase mask */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Status 1 Register */
+/*----------------------------------------------------------------------*/
+#define TSS_STATUS_RCV 0x08 /* Status received */
+#define TSS_MSG_SEND 0x40 /* Message sent */
+#define TSS_CMD_PH_CMP 0x20 /* command phase done */
+#define TSS_DATA_PH_CMP 0x10 /* Data phase done */
+#define TSS_STATUS_SEND 0x08 /* Status sent */
+#define TSS_XFER_CMP 0x04 /* Transfer completed */
+#define TSS_SEL_CMP 0x02 /* Selection completed */
+#define TSS_ARB_CMP 0x01 /* Arbitration completed */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Status 2 Register */
+/*----------------------------------------------------------------------*/
+#define TSS_CMD_ABTED 0x80 /* Command aborted */
+#define TSS_OFFSET_0 0x40 /* Offset counter zero */
+#define TSS_FIFO_FULL 0x20 /* FIFO full */
+#define TSS_TIMEOUT_0 0x10 /* Timeout counter zero */
+#define TSS_BUSY_RLS 0x08 /* Busy release */
+#define TSS_PH_MISMATCH 0x04 /* Phase mismatch */
+#define TSS_SCSI_BUS_EN 0x02 /* SCSI data bus enable */
+#define TSS_SCSIRST 0x01 /* SCSI bus reset in progress */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Interrupt Register */
+/*----------------------------------------------------------------------*/
+#define TSS_RESEL_INT 0x80 /* Reselected interrupt */
+#define TSS_SEL_TIMEOUT 0x40 /* Selected/reselected timeout */
+#define TSS_BUS_SERV 0x20
+#define TSS_SCSIRST_INT 0x10 /* SCSI bus reset detected */
+#define TSS_DISC_INT 0x08 /* Disconnected interrupt */
+#define TSS_SEL_INT 0x04 /* Select interrupt */
+#define TSS_SCAM_SEL 0x02 /* SCAM selected */
+#define TSS_FUNC_COMP 0x01
+
+/*----------------------------------------------------------------------*/
+/* SCSI Phase Codes. */
+/*----------------------------------------------------------------------*/
+#define DATA_OUT 0
+#define DATA_IN 1 /* 4 */
+#define CMD_OUT 2
+#define STATUS_IN 3 /* 6 */
+#define MSG_OUT 6 /* 3 */
+#define MSG_IN 7
+
+
+
+/*----------------------------------------------------------------------*/
+/* Command Codes of Tulip xfer Command register */
+/*----------------------------------------------------------------------*/
+#define TAX_X_FORC 0x02
+#define TAX_X_ABT 0x04
+#define TAX_X_CLR_FIFO 0x08
+
+#define TAX_X_IN 0x21
+#define TAX_X_OUT 0x01
+#define TAX_SG_IN 0xA1
+#define TAX_SG_OUT 0x81
+
+/*----------------------------------------------------------------------*/
+/* Tulip Interrupt Register */
+/*----------------------------------------------------------------------*/
+#define XCMP 0x01
+#define FCMP 0x02
+#define XABT 0x04
+#define XERR 0x08
+#define SCMP 0x10
+#define IPEND 0x80
+
+/*----------------------------------------------------------------------*/
+/* Tulip DMA Status Register */
+/*----------------------------------------------------------------------*/
+#define XPEND 0x01 /* Transfer pending */
+#define FEMPTY 0x02 /* FIFO empty */
+
+
+
+/*----------------------------------------------------------------------*/
+/* bit definition for TUL_GCTRL */
+/*----------------------------------------------------------------------*/
+#define EXTSG 0x80
+#define EXTAD 0x60
+#define SEG4K 0x08
+#define EEPRG 0x04
+#define MRMUL 0x02
+
+/*----------------------------------------------------------------------*/
+/* bit definition for TUL_NVRAM */
+/*----------------------------------------------------------------------*/
+#define SE2CS 0x08
+#define SE2CLK 0x04
+#define SE2DO 0x02
+#define SE2DI 0x01
+
+
+/************************************************************************/
+/* Scatter-Gather Element Structure */
+/************************************************************************/
+typedef struct SG_Struc {
+ U32 SG_Ptr; /* Data Pointer */
+ U32 SG_Len; /* Data Length */
+} SG;
+
+/***********************************************************************
+ SCSI Control Block
+************************************************************************/
+typedef struct Scsi_Ctrl_Blk {
+ struct Scsi_Ctrl_Blk *SCB_NxtScb;
+ UBYTE SCB_Status; /*4 */
+ UBYTE SCB_NxtStat; /*5 */
+ UBYTE SCB_Mode; /*6 */
+ UBYTE SCB_Msgin; /*7 SCB_Res0 */
+ UWORD SCB_SGIdx; /*8 */
+ UWORD SCB_SGMax; /*A */
+#ifdef ALPHA
+ U32 SCB_Reserved[2]; /*C */
+#else
+ U32 SCB_Reserved[3]; /*C */
+#endif
+
+ U32 SCB_XferLen; /*18 Current xfer len */
+ U32 SCB_TotXLen; /*1C Total xfer len */
+ U32 SCB_PAddr; /*20 SCB phy. Addr. */
+
+ UBYTE SCB_Opcode; /*24 SCB command code */
+ UBYTE SCB_Flags; /*25 SCB Flags */
+ UBYTE SCB_Target; /*26 Target Id */
+ UBYTE SCB_Lun; /*27 Lun */
+ U32 SCB_BufPtr; /*28 Data Buffer Pointer */
+ U32 SCB_BufLen; /*2C Data Allocation Length */
+ UBYTE SCB_SGLen; /*30 SG list # */
+ UBYTE SCB_SenseLen; /*31 Sense Allocation Length */
+ UBYTE SCB_HaStat; /*32 */
+ UBYTE SCB_TaStat; /*33 */
+ UBYTE SCB_CDBLen; /*34 CDB Length */
+ UBYTE SCB_Ident; /*35 Identify */
+ UBYTE SCB_TagMsg; /*36 Tag Message */
+ UBYTE SCB_TagId; /*37 Queue Tag */
+ UBYTE SCB_CDB[12]; /*38 */
+ U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */
+ U32 SCB_SensePtr; /*48 Sense data pointer */
+ void (*SCB_Post) (BYTE *, BYTE *); /*4C POST routine */
+ unsigned char *SCB_Srb; /*50 SRB Pointer */
+ SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */
+} SCB;
+
+/* Bit Definition for SCB_Status */
+#define SCB_RENT 0x01
+#define SCB_PEND 0x02
+#define SCB_CONTIG 0x04 /* Contigent Allegiance */
+#define SCB_SELECT 0x08
+#define SCB_BUSY 0x10
+#define SCB_DONE 0x20
+
+
+/* Opcodes of SCB_Opcode */
+#define ExecSCSI 0x1
+#define BusDevRst 0x2
+#define AbortCmd 0x3
+
+
+/* Bit Definition for SCB_Mode */
+#define SCM_RSENS 0x01 /* request sense mode */
+
+
+/* Bit Definition for SCB_Flags */
+#define SCF_DONE 0x01
+#define SCF_POST 0x02
+#define SCF_SENSE 0x04
+#define SCF_DIR 0x18
+#define SCF_NO_DCHK 0x00
+#define SCF_DIN 0x08
+#define SCF_DOUT 0x10
+#define SCF_NO_XF 0x18
+#define SCF_WR_VF 0x20 /* Write verify turn on */
+#define SCF_POLL 0x40
+#define SCF_SG 0x80
+
+/* Error Codes for SCB_HaStat */
+#define HOST_SEL_TOUT 0x11
+#define HOST_DO_DU 0x12
+#define HOST_BUS_FREE 0x13
+#define HOST_BAD_PHAS 0x14
+#define HOST_INV_CMD 0x16
+#define HOST_ABORTED 0x1A /* 07/21/98 */
+#define HOST_SCSI_RST 0x1B
+#define HOST_DEV_RST 0x1C
+
+/* Error Codes for SCB_TaStat */
+#define TARGET_CHKCOND 0x02
+#define TARGET_BUSY 0x08
+#define QUEUE_FULL 0x28
+
+/* SCSI MESSAGE */
+#define MSG_COMP 0x00
+#define MSG_EXTEND 0x01
+#define MSG_SDP 0x02
+#define MSG_RESTORE 0x03
+#define MSG_DISC 0x04
+#define MSG_IDE 0x05
+#define MSG_ABORT 0x06
+#define MSG_REJ 0x07
+#define MSG_NOP 0x08
+#define MSG_PARITY 0x09
+#define MSG_LINK_COMP 0x0A
+#define MSG_LINK_FLAG 0x0B
+#define MSG_DEVRST 0x0C
+#define MSG_ABORT_TAG 0x0D
+
+/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
+#define MSG_STAG 0x20
+#define MSG_HTAG 0x21
+#define MSG_OTAG 0x22
+
+#define MSG_IGNOREWIDE 0x23
+
+#define MSG_IDENT 0x80
+
+/***********************************************************************
+ Target Device Control Structure
+**********************************************************************/
+
+typedef struct Tar_Ctrl_Struc {
+ UWORD TCS_Flags; /* 0 */
+ UBYTE TCS_JS_Period; /* 2 */
+ UBYTE TCS_SConfig0; /* 3 */
+
+ UWORD TCS_DrvFlags; /* 4 */
+ UBYTE TCS_DrvHead; /* 6 */
+ UBYTE TCS_DrvSector; /* 7 */
+} TCS;
+
+/***********************************************************************
+ Target Device Control Structure
+**********************************************************************/
+
+/* Bit Definition for TCF_Flags */
+#define TCF_SCSI_RATE 0x0007
+#define TCF_EN_DISC 0x0008
+#define TCF_NO_SYNC_NEGO 0x0010
+#define TCF_NO_WDTR 0x0020
+#define TCF_EN_255 0x0040
+#define TCF_EN_START 0x0080
+#define TCF_WDTR_DONE 0x0100
+#define TCF_SYNC_DONE 0x0200
+#define TCF_BUSY 0x0400
+
+
+/* Bit Definition for TCF_DrvFlags */
+#define TCF_DRV_BUSY 0x01 /* Indicate target busy(driver) */
+#define TCF_DRV_EN_TAG 0x0800
+#define TCF_DRV_255_63 0x0400
+
+typedef struct I91u_Adpt_Struc {
+ UWORD ADPT_BIOS; /* 0 */
+ UWORD ADPT_BASE; /* 1 */
+ UBYTE ADPT_Bus; /* 2 */
+ UBYTE ADPT_Device; /* 3 */
+ UBYTE ADPT_INTR; /* 4 */
+} INI_ADPT_STRUCT;
+
+
+/***********************************************************************
+ Host Adapter Control Structure
+************************************************************************/
+typedef struct Ha_Ctrl_Struc {
+ UWORD HCS_Base; /* 00 */
+ UWORD HCS_BIOS; /* 02 */
+ UBYTE HCS_Intr; /* 04 */
+ UBYTE HCS_SCSI_ID; /* 05 */
+ UBYTE HCS_MaxTar; /* 06 */
+ UBYTE HCS_NumScbs; /* 07 */
+
+ UBYTE HCS_Flags; /* 08 */
+ UBYTE HCS_Index; /* 09 */
+ UBYTE HCS_HaId; /* 0A */
+ UBYTE HCS_Config; /* 0B */
+ UWORD HCS_IdMask; /* 0C */
+ UBYTE HCS_Semaph; /* 0E */
+ UBYTE HCS_Phase; /* 0F */
+ UBYTE HCS_JSStatus0; /* 10 */
+ UBYTE HCS_JSInt; /* 11 */
+ UBYTE HCS_JSStatus1; /* 12 */
+ UBYTE HCS_SConf1; /* 13 */
+
+ UBYTE HCS_Msg[8]; /* 14 */
+ SCB *HCS_NxtAvail; /* 1C */
+ SCB *HCS_Scb; /* 20 */
+ SCB *HCS_ScbEnd; /* 24 */
+ SCB *HCS_NxtPend; /* 28 */
+ SCB *HCS_NxtContig; /* 2C */
+ SCB *HCS_ActScb; /* 30 */
+ TCS *HCS_ActTcs; /* 34 */
+
+ SCB *HCS_FirstAvail; /* 38 */
+ SCB *HCS_LastAvail; /* 3C */
+ SCB *HCS_FirstPend; /* 40 */
+ SCB *HCS_LastPend; /* 44 */
+ SCB *HCS_FirstBusy; /* 48 */
+ SCB *HCS_LastBusy; /* 4C */
+ SCB *HCS_FirstDone; /* 50 */
+ SCB *HCS_LastDone; /* 54 */
+ UBYTE HCS_MaxTags[16]; /* 58 */
+ UBYTE HCS_ActTags[16]; /* 68 */
+ TCS HCS_Tcs[MAX_TARGETS]; /* 78 */
+ ULONG pSRB_head; /* SRB save queue header */
+ ULONG pSRB_tail; /* SRB save queue tail */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spinlock_t HCS_AvailLock;
+ spinlock_t HCS_SemaphLock;
+ spinlock_t pSRB_lock; /* SRB queue lock */
+#endif
+} HCS;
+
+/* Bit Definition for HCB_Config */
+#define HCC_SCSI_RESET 0x01
+#define HCC_EN_PAR 0x02
+#define HCC_ACT_TERM1 0x04
+#define HCC_ACT_TERM2 0x08
+#define HCC_AUTO_TERM 0x10
+#define HCC_EN_PWR 0x80
+
+/* Bit Definition for HCB_Flags */
+#define HCF_EXPECT_DISC 0x01
+#define HCF_EXPECT_SELECT 0x02
+#define HCF_EXPECT_RESET 0x10
+#define HCF_EXPECT_DONE_DISC 0x20
+
+/******************************************************************
+ Serial EEProm
+*******************************************************************/
+
+typedef struct _NVRAM_SCSI { /* SCSI channel configuration */
+ UCHAR NVM_ChSCSIID; /* 0Ch -> Channel SCSI ID */
+ UCHAR NVM_ChConfig1; /* 0Dh -> Channel config 1 */
+ UCHAR NVM_ChConfig2; /* 0Eh -> Channel config 2 */
+ UCHAR NVM_NumOfTarg; /* 0Fh -> Number of SCSI target */
+ /* SCSI target configuration */
+ UCHAR NVM_Targ0Config; /* 10h -> Target 0 configuration */
+ UCHAR NVM_Targ1Config; /* 11h -> Target 1 configuration */
+ UCHAR NVM_Targ2Config; /* 12h -> Target 2 configuration */
+ UCHAR NVM_Targ3Config; /* 13h -> Target 3 configuration */
+ UCHAR NVM_Targ4Config; /* 14h -> Target 4 configuration */
+ UCHAR NVM_Targ5Config; /* 15h -> Target 5 configuration */
+ UCHAR NVM_Targ6Config; /* 16h -> Target 6 configuration */
+ UCHAR NVM_Targ7Config; /* 17h -> Target 7 configuration */
+ UCHAR NVM_Targ8Config; /* 18h -> Target 8 configuration */
+ UCHAR NVM_Targ9Config; /* 19h -> Target 9 configuration */
+ UCHAR NVM_TargAConfig; /* 1Ah -> Target A configuration */
+ UCHAR NVM_TargBConfig; /* 1Bh -> Target B configuration */
+ UCHAR NVM_TargCConfig; /* 1Ch -> Target C configuration */
+ UCHAR NVM_TargDConfig; /* 1Dh -> Target D configuration */
+ UCHAR NVM_TargEConfig; /* 1Eh -> Target E configuration */
+ UCHAR NVM_TargFConfig; /* 1Fh -> Target F configuration */
+} NVRAM_SCSI;
+
+typedef struct _NVRAM {
+/*----------header ---------------*/
+ USHORT NVM_Signature; /* 0,1: Signature */
+ UCHAR NVM_Size; /* 2: Size of data structure */
+ UCHAR NVM_Revision; /* 3: Revision of data structure */
+ /* ----Host Adapter Structure ---- */
+ UCHAR NVM_ModelByte0; /* 4: Model number (byte 0) */
+ UCHAR NVM_ModelByte1; /* 5: Model number (byte 1) */
+ UCHAR NVM_ModelInfo; /* 6: Model information */
+ UCHAR NVM_NumOfCh; /* 7: Number of SCSI channel */
+ UCHAR NVM_BIOSConfig1; /* 8: BIOS configuration 1 */
+ UCHAR NVM_BIOSConfig2; /* 9: BIOS configuration 2 */
+ UCHAR NVM_HAConfig1; /* A: Hoat adapter configuration 1 */
+ UCHAR NVM_HAConfig2; /* B: Hoat adapter configuration 2 */
+ NVRAM_SCSI NVM_SCSIInfo[2];
+ UCHAR NVM_reserved[10];
+ /* ---------- CheckSum ---------- */
+ USHORT NVM_CheckSum; /* 0x3E, 0x3F: Checksum of NVRam */
+} NVRAM, *PNVRAM;
+
+/* Bios Configuration for nvram->BIOSConfig1 */
+#define NBC1_ENABLE 0x01 /* BIOS enable */
+#define NBC1_8DRIVE 0x02 /* Support more than 2 drives */
+#define NBC1_REMOVABLE 0x04 /* Support removable drive */
+#define NBC1_INT19 0x08 /* Intercept int 19h */
+#define NBC1_BIOSSCAN 0x10 /* Dynamic BIOS scan */
+#define NBC1_LUNSUPPORT 0x40 /* Support LUN */
+
+/* HA Configuration Byte 1 */
+#define NHC1_BOOTIDMASK 0x0F /* Boot ID number */
+#define NHC1_LUNMASK 0x70 /* Boot LUN number */
+#define NHC1_CHANMASK 0x80 /* Boot Channel number */
+
+/* Bit definition for nvram->SCSIconfig1 */
+#define NCC1_BUSRESET 0x01 /* Reset SCSI bus at power up */
+#define NCC1_PARITYCHK 0x02 /* SCSI parity enable */
+#define NCC1_ACTTERM1 0x04 /* Enable active terminator 1 */
+#define NCC1_ACTTERM2 0x08 /* Enable active terminator 2 */
+#define NCC1_AUTOTERM 0x10 /* Enable auto terminator */
+#define NCC1_PWRMGR 0x80 /* Enable power management */
+
+/* Bit definition for SCSI Target configuration byte */
+#define NTC_DISCONNECT 0x08 /* Enable SCSI disconnect */
+#define NTC_SYNC 0x10 /* SYNC_NEGO */
+#define NTC_NO_WDTR 0x20 /* SYNC_NEGO */
+#define NTC_1GIGA 0x40 /* 255 head / 63 sectors (64/32) */
+#define NTC_SPINUP 0x80 /* Start disk drive */
+
+/* Default NVRam values */
+#define INI_SIGNATURE 0xC925
+#define NBC1_DEFAULT (NBC1_ENABLE)
+#define NCC1_DEFAULT (NCC1_BUSRESET | NCC1_AUTOTERM | NCC1_PARITYCHK)
+#define NTC_DEFAULT (NTC_NO_WDTR | NTC_1GIGA | NTC_DISCONNECT)
+
+/* SCSI related definition */
+#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */
+#define DISC_ALLOW 0xC0 /* Disconnect is allowed */
+#define SCSICMD_RequestSense 0x03
+
+
+/*----------------------------------------------------------------------*/
+/* PCI */
+/*----------------------------------------------------------------------*/
+#define PCI_FUNCTION_ID 0xB1
+#define PCI_BIOS_PRESENT 0x01
+#define FIND_PCI_DEVICE 0x02
+#define FIND_PCI_CLASS_CODE 0x03
+#define GENERATE_SPECIAL_CYCLE 0x06
+#define READ_CONFIG_BYTE 0x08
+#define READ_CONFIG_WORD 0x09
+#define READ_CONFIG_DWORD 0x0A
+#define WRITE_CONFIG_BYTE 0x0B
+#define WRITE_CONFIG_WORD 0x0C
+#define WRITE_CONFIG_DWORD 0x0D
+
+#define SUCCESSFUL 0x00
+#define FUNC_NOT_SUPPORTED 0x81
+#define BAD_VENDOR_ID 0x83 /* Bad vendor ID */
+#define DEVICE_NOT_FOUND 0x86 /* PCI device not found */
+#define BAD_REGISTER_NUMBER 0x87
+
+#define MAX_PCI_DEVICES 21 /* Maximum devices supportted */
+
+#define MAX_PCI_CHANL 4
+
+typedef struct _BIOS32_ENTRY_STRUCTURE {
+ DWORD Signatures; /* Should be "_32_" */
+ DWORD BIOS32Entry; /* 32-bit physical address */
+ BYTE Revision; /* Revision level, should be 0 */
+ BYTE Length; /* Multiply of 16, should be 1 */
+ BYTE CheckSum; /* Checksum of whole structure */
+ BYTE Reserved[5]; /* Reserved */
+} BIOS32_ENTRY_STRUCTURE, *PBIOS32_ENTRY_STRUCTURE;
+
+typedef struct {
+ union {
+ unsigned int eax;
+ struct {
+ unsigned short ax;
+ } word;
+ struct {
+ unsigned char al;
+ unsigned char ah;
+ } byte;
+ } eax;
+ union {
+ unsigned int ebx;
+ struct {
+ unsigned short bx;
+ } word;
+ struct {
+ unsigned char bl;
+ unsigned char bh;
+ } byte;
+ } ebx;
+ union {
+ unsigned int ecx;
+ struct {
+ unsigned short cx;
+ } word;
+ struct {
+ unsigned char cl;
+ unsigned char ch;
+ } byte;
+ } ecx;
+ union {
+ unsigned int edx;
+ struct {
+ unsigned short dx;
+ } word;
+ struct {
+ unsigned char dl;
+ unsigned char dh;
+ } byte;
+ } edx;
+ union {
+ unsigned int edi;
+ struct {
+ unsigned short di;
+ } word;
+ } edi;
+ union {
+ unsigned int esi;
+ struct {
+ unsigned short si;
+ } word;
+ } esi;
+} REGS;
+
+typedef union { /* Union define for mechanism 1 */
+ struct {
+ unsigned char RegNum;
+ unsigned char FcnNum:3;
+ unsigned char DeviceNum:5;
+ unsigned char BusNum;
+ unsigned char Reserved:7;
+ unsigned char Enable:1;
+ } sConfigAdr;
+ unsigned long lConfigAdr;
+} CONFIG_ADR;
+
+typedef union { /* Union define for mechanism 2 */
+ struct {
+ unsigned char RegNum;
+ unsigned char DeviceNum;
+ unsigned short Reserved;
+ } sHostAdr;
+ unsigned long lHostAdr;
+} HOST_ADR;
+
+typedef struct _HCSinfo {
+ ULONG base;
+ UCHAR vec;
+ UCHAR bios; /* High byte of BIOS address */
+ USHORT BaseAndBios; /* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */
+} HCSINFO;
+
+#define TUL_RD(x,y) (UCHAR)(inb( (int)((ULONG)(x+y)) ))
+#define TUL_RDLONG(x,y) (ULONG)(inl((int)((ULONG)(x+y)) ))
+#define TUL_WR( adr,data) outb( (UCHAR)(data), (int)(adr))
+#define TUL_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr))
+#define TUL_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr))
+
+#define SCSI_ABORT_SNOOZE 0
+#define SCSI_ABORT_SUCCESS 1
+#define SCSI_ABORT_PENDING 2
+#define SCSI_ABORT_BUSY 3
+#define SCSI_ABORT_NOT_RUNNING 4
+#define SCSI_ABORT_ERROR 5
+
+#define SCSI_RESET_SNOOZE 0
+#define SCSI_RESET_PUNT 1
+#define SCSI_RESET_SUCCESS 2
+#define SCSI_RESET_PENDING 3
+#define SCSI_RESET_WAKEUP 4
+#define SCSI_RESET_NOT_RUNNING 5
+#define SCSI_RESET_ERROR 6
+
+#define SCSI_RESET_SYNCHRONOUS 0x01
+#define SCSI_RESET_ASYNCHRONOUS 0x02
+#define SCSI_RESET_SUGGEST_BUS_RESET 0x04
+#define SCSI_RESET_SUGGEST_HOST_RESET 0x08
+
+#define SCSI_RESET_BUS_RESET 0x100
+#define SCSI_RESET_HOST_RESET 0x200
+#define SCSI_RESET_ACTION 0xff
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 0b1337581..bd65b5e84 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -1567,7 +1567,7 @@ ibmmca_detect (Scsi_Host_Template * template)
/* first look for the SCSI integrated on the motherboard */
pos2 = mca_read_stored_pos(MCA_INTEGSCSI, 2);
- if (pos2 != 0xff) {
+// if (pos2 != 0xff) {
if ((pos2 & 1) == 0) {
port = IM_IO_PORT + ((pos2 & 0x0e) << 2);
} else {
@@ -1584,7 +1584,7 @@ ibmmca_detect (Scsi_Host_Template * template)
mca_set_adapter_procfn(MCA_INTEGSCSI, (MCA_ProcFn) ibmmca_getinfo,
shpnt);
}
- }
+// }
/* now look for other adapters */
list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index dd49bcfb7..4f7315e04 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -23,6 +23,8 @@
* Ver 0.6 Jan 27 98 Allow disabling of SCSI command translation layer
* for access through /dev/sg.
* Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
+ * Ver 0.7 Dev 04 98 Ignore commands where lun != 0 to avoid multiple
+ * detection of devices with CONFIG_SCSI_MULTI_LUN
*/
#define IDESCSI_VERSION "0.6"
@@ -728,6 +730,9 @@ int idescsi_queue (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
printk (KERN_ERR "ide-scsi: drive id %d not present\n", cmd->target);
goto abort;
}
+ if (cmd->lun != 0) { /* Only respond to LUN 0. Drop others */
+ goto abort;
+ }
scsi = drive->driver_data;
pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index 7bb8f961a..deddc28ba 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -4,8 +4,7 @@
* (The IMM is the embedded controller in the ZIP Plus drive.)
*
* Current Maintainer: David Campbell (Perth, Western Australia)
- * campbell@gear.torque.net
- * dcampbel@p01.as17.honeywell.com.au
+ * campbell@torque.net
*
* My unoffical company acronym list is 21 pages long:
* FLA: Four letter acronym with built in facility for
@@ -31,7 +30,7 @@ static int device_check(int host_no);
#include "sd.h"
#include "hosts.h"
typedef struct {
- struct pardevice *dev; /* Parport device entry */
+ struct pardevice *dev; /* Parport device entry */
int base; /* Actual port address */
int mode; /* Transfer mode */
int host; /* Host number (for proc) */
@@ -65,23 +64,24 @@ static imm_struct imm_hosts[NO_HOSTS] =
#define IMM_BASE(x) imm_hosts[(x)].base
-int parbus_base[NO_HOSTS] = {0x03bc, 0x0378, 0x0278, 0x0000};
+int parbus_base[NO_HOSTS] =
+{0x03bc, 0x0378, 0x0278, 0x0000};
void imm_wakeup(void *ref)
{
imm_struct *imm_dev = (imm_struct *) ref;
if (!imm_dev->p_busy)
- return;
+ return;
if (parport_claim(imm_dev->dev)) {
- printk("imm: bug in imm_wakeup\n");
- return;
+ printk("imm: bug in imm_wakeup\n");
+ return;
}
imm_dev->p_busy = 0;
imm_dev->base = imm_dev->dev->port->base;
if (imm_dev->cur_cmd)
- imm_dev->cur_cmd->SCp.phase++;
+ imm_dev->cur_cmd->SCp.phase++;
return;
}
@@ -97,12 +97,11 @@ int imm_release(struct Scsi_Host *host)
static int imm_pb_claim(int host_no)
{
if (parport_claim(imm_hosts[host_no].dev)) {
- imm_hosts[host_no].p_busy = 1;
- return 1;
+ imm_hosts[host_no].p_busy = 1;
+ return 1;
}
-
if (imm_hosts[host_no].cur_cmd)
- imm_hosts[host_no].cur_cmd->SCp.phase++;
+ imm_hosts[host_no].cur_cmd->SCp.phase++;
return 0;
}
@@ -112,40 +111,7 @@ static int imm_pb_claim(int host_no)
* Parallel port probing routines *
***************************************************************************/
-#ifndef MODULE
-/*
- * Command line parameters (for built-in driver):
- *
- * Syntax: imm=base[,mode[,use_sg]]
- *
- * For example: imm=0x378 or imm=0x378,0,3
- *
- */
-
-void imm_setup(char *str, int *ints)
-{
- static int x = 0;
-
- if (x == 0) { /* Disable ALL known ports */
- int i;
-
- for (i = 0; i < NO_HOSTS; i++)
- parbus_base[i] = 0x0000;
- }
- switch (ints[0]) {
- case 3:
- imm_sg = ints[3];
- case 2:
- imm_hosts[x].mode = ints[2];
- parbus_base[x] = ints[1];
- break;
- default:
- printk("IMM: I only use between 2 to 3 parameters.\n");
- break;
- }
- x++;
-}
-#else
+#ifdef MODULE
Scsi_Host_Template driver_template = IMM;
#include "scsi_module.c"
#endif
@@ -162,100 +128,95 @@ int imm_detect(Scsi_Host_Template * host)
try_again = 0;
if (!pb) {
- printk("imm: parport reports no devices.\n");
- return 0;
+ printk("imm: parport reports no devices.\n");
+ return 0;
}
-
retry_entry:
for (i = 0; pb; i++, pb = pb->next) {
- int modes, ppb;
+ int modes, ppb;
- imm_hosts[i].dev =
- parport_register_device(pb, "imm", NULL, imm_wakeup,
- NULL, 0, (void *) &imm_hosts[i]);
+ imm_hosts[i].dev =
+ parport_register_device(pb, "imm", NULL, imm_wakeup,
+ NULL, 0, (void *) &imm_hosts[i]);
if (!imm_hosts[i].dev)
- continue;
+ continue;
- /* Claim the bus so it remembers what we do to the control
- * registers. [ CTR and ECP ]
- */
- if (imm_pb_claim(i))
- {
+ /* Claim the bus so it remembers what we do to the control
+ * registers. [ CTR and ECP ]
+ */
+ if (imm_pb_claim(i)) {
unsigned long now = jiffies;
- while (imm_hosts[i].p_busy)
- {
+ while (imm_hosts[i].p_busy) {
schedule(); /* We are safe to schedule here */
- if (jiffies > now + 3*HZ)
- {
+ if (time_after(jiffies, now + 3 * HZ)) {
printk(KERN_ERR "imm%d: failed to claim parport because a "
- "pardevice is owning the port for too longtime!\n",
+ "pardevice is owning the port for too longtime!\n",
i);
return 0;
}
}
}
+ ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
+ w_ctr(ppb, 0x0c);
+ modes = imm_hosts[i].dev->port->modes;
+
+ /* Mode detection works up the chain of speed
+ * This avoids a nasty if-then-else-if-... tree
+ */
+ imm_hosts[i].mode = IMM_NIBBLE;
+
+ if (modes & PARPORT_MODE_PCPS2)
+ imm_hosts[i].mode = IMM_PS2;
+
+ if (modes & PARPORT_MODE_PCECPPS2) {
+ w_ecr(ppb, 0x20);
+ imm_hosts[i].mode = IMM_PS2;
+ }
+ if (modes & PARPORT_MODE_PCECPEPP)
+ w_ecr(ppb, 0x80);
+
+ /* Done configuration */
+ imm_pb_release(i);
- ppb = IMM_BASE(i) = imm_hosts[i].dev->port->base;
- w_ctr(ppb, 0x0c);
- modes = imm_hosts[i].dev->port->modes;
-
- /* Mode detection works up the chain of speed
- * This avoids a nasty if-then-else-if-... tree
- */
- imm_hosts[i].mode = IMM_NIBBLE;
-
- if (modes & PARPORT_MODE_PCPS2)
- imm_hosts[i].mode = IMM_PS2;
-
- if (modes & PARPORT_MODE_PCECPPS2) {
- w_ecr(ppb, 0x20);
- imm_hosts[i].mode = IMM_PS2;
- }
- if (modes & PARPORT_MODE_PCECPEPP)
- w_ecr(ppb, 0x80);
-
- /* Done configuration */
- imm_pb_release(i);
-
- if (imm_init(i)) {
- parport_unregister_device(imm_hosts[i].dev);
- continue;
- }
- /* now the glue ... */
- switch (imm_hosts[i].mode) {
- case IMM_NIBBLE:
- ports = 3;
- break;
- case IMM_PS2:
- ports = 3;
- break;
- case IMM_EPP_8:
- case IMM_EPP_16:
- case IMM_EPP_32:
- ports = 8;
- break;
- default: /* Never gets here */
- continue;
- }
-
- host->can_queue = IMM_CAN_QUEUE;
- host->sg_tablesize = imm_sg;
- hreg = scsi_register(host, 0);
- hreg->io_port = pb->base;
- hreg->n_io_port = ports;
- hreg->dma_channel = -1;
- hreg->unique_id = i;
- imm_hosts[i].host = hreg->host_no;
- nhosts++;
+ if (imm_init(i)) {
+ parport_unregister_device(imm_hosts[i].dev);
+ continue;
+ }
+ /* now the glue ... */
+ switch (imm_hosts[i].mode) {
+ case IMM_NIBBLE:
+ ports = 3;
+ break;
+ case IMM_PS2:
+ ports = 3;
+ break;
+ case IMM_EPP_8:
+ case IMM_EPP_16:
+ case IMM_EPP_32:
+ ports = 8;
+ break;
+ default: /* Never gets here */
+ continue;
+ }
+
+ host->can_queue = IMM_CAN_QUEUE;
+ host->sg_tablesize = imm_sg;
+ hreg = scsi_register(host, 0);
+ hreg->io_port = pb->base;
+ hreg->n_io_port = ports;
+ hreg->dma_channel = -1;
+ hreg->unique_id = i;
+ imm_hosts[i].host = hreg->host_no;
+ nhosts++;
}
if (nhosts == 0) {
- if (try_again == 1)
- return 0;
- try_again = 1;
- goto retry_entry;
+ if (try_again == 1)
+ return 0;
+ try_again = 1;
+ goto retry_entry;
} else
- return 1; /* return number of hosts detected */
+ return 1; /* return number of hosts detected */
}
/* This is to give the imm driver a way to modify the timings (and other
@@ -265,22 +226,11 @@ int imm_detect(Scsi_Host_Template * host)
* testing...
* Also gives a method to use a script to obtain optimum timings (TODO)
*/
-
-static inline int imm_strncmp(const char *a, const char *b, int len)
-{
- int loop;
- for (loop = 0; loop < len; loop++)
- if (a[loop] != b[loop])
- return 1;
-
- return 0;
-}
-
static inline int imm_proc_write(int hostno, char *buffer, int length)
{
unsigned long x;
- if ((length > 5) && (imm_strncmp(buffer, "mode=", 5) == 0)) {
+ if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
x = simple_strtoul(buffer + 5, NULL, 0);
imm_hosts[hostno].mode = x;
return length;
@@ -378,7 +328,7 @@ static unsigned char imm_wait(int host_no)
if (k)
return (r & 0xb8);
- /* Counter expired - Time out occured */
+ /* Counter expired - Time out occurred */
imm_fail(host_no, DID_TIME_OUT);
printk("imm timeout in imm_wait\n");
return 0; /* command timed out */
@@ -445,42 +395,34 @@ static inline void ecp_sync(unsigned short ppb)
int i;
if ((r_ecr(ppb) & 0xe0) != 0x80)
- return;
+ return;
for (i = 0; i < 100; i++) {
- if (r_ecr(ppb) & 0x01)
- return;
- udelay(5);
+ if (r_ecr(ppb) & 0x01)
+ return;
+ udelay(5);
}
printk("imm: ECP sync failed as data still present in FIFO.\n");
}
-static inline int imm_byte_out(unsigned short base, const char *buffer, int len)
+static int imm_byte_out(unsigned short base, const char *buffer, int len)
{
int i;
- w_ctr(base, 0x4); /* aimmrently a sane mode */
+ w_ctr(base, 0x4); /* apparently a sane mode */
for (i = len >> 1; i; i--) {
w_dtr(base, *buffer++);
w_ctr(base, 0x5); /* Drop STROBE low */
w_dtr(base, *buffer++);
w_ctr(base, 0x0); /* STROBE high + INIT low */
}
- w_ctr(base, 0x4); /* aimmrently a sane mode */
+ w_ctr(base, 0x4); /* apparently a sane mode */
return 1; /* All went well - we hope! */
}
-static inline int imm_epp_out(unsigned short base, char *buffer, int len)
+static int imm_nibble_in(unsigned short base, char *buffer, int len)
{
- int i;
- for (i = len; i; i--)
- w_epp(base, *buffer++);
- return 1;
-}
-
-static inline int imm_nibble_in(unsigned short base, char *buffer, int len)
-{
- unsigned char h, l;
+ unsigned char l;
int i;
/*
@@ -489,16 +431,15 @@ static inline int imm_nibble_in(unsigned short base, char *buffer, int len)
w_ctr(base, 0x4);
for (i = len; i; i--) {
w_ctr(base, 0x6);
- l = r_str(base);
+ l = (r_str(base) & 0xf0) >> 4;
w_ctr(base, 0x5);
- h = r_str(base);
+ *buffer++ = (r_str(base) & 0xf0) | l;
w_ctr(base, 0x4);
- *buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
}
return 1; /* All went well - we hope! */
}
-static inline int imm_byte_in(unsigned short base, char *buffer, int len)
+static int imm_byte_in(unsigned short base, char *buffer, int len)
{
int i;
@@ -514,14 +455,6 @@ static inline int imm_byte_in(unsigned short base, char *buffer, int len)
return 1; /* All went well - we hope! */
}
-static inline int imm_epp_in(unsigned short base, char *buffer, int len)
-{
- int i;
- for (i = len; i; i--)
- *buffer++ = r_epp(base);
- return 1;
-}
-
static int imm_out(int host_no, char *buffer, int len)
{
int r;
@@ -543,11 +476,21 @@ static int imm_out(int host_no, char *buffer, int len)
case IMM_EPP_32:
case IMM_EPP_16:
case IMM_EPP_8:
- epp_reset(ppb);
- w_ctr(ppb, 0x4);
- r = imm_epp_out(ppb, buffer, len);
- w_ctr(ppb, 0xc);
- ecp_sync(ppb);
+ epp_reset(ppb);
+ w_ctr(ppb, 0x4);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ outsw(ppb + 4, buffer, len >> 1);
+#else
+ if (!(((long) buffer | len) & 0x03))
+ outsl(ppb + 4, buffer, len >> 2);
+#endif
+ else
+ outsb(ppb + 4, buffer, len);
+ w_ctr(ppb, 0xc);
+ r = !(r_str(ppb) & 0x01);
+ w_ctr(ppb, 0xc);
+ ecp_sync(ppb);
break;
case IMM_NIBBLE:
@@ -595,11 +538,21 @@ static int imm_in(int host_no, char *buffer, int len)
case IMM_EPP_32:
case IMM_EPP_16:
case IMM_EPP_8:
- epp_reset(ppb);
- w_ctr(ppb, 0x24);
- r = imm_epp_in(ppb, buffer, len);
- w_ctr(ppb, 0x2c);
- ecp_sync(ppb);
+ epp_reset(ppb);
+ w_ctr(ppb, 0x24);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ insw(ppb + 4, buffer, len >> 1);
+#else
+ if (!(((long) buffer | len) & 0x03))
+ insl(ppb + 4, buffer, len >> 2);
+#endif
+ else
+ insb(ppb + 4, buffer, len);
+ w_ctr(ppb, 0x2c);
+ r = !(r_str(ppb) & 0x01);
+ w_ctr(ppb, 0x2c);
+ ecp_sync(ppb);
break;
default:
@@ -756,8 +709,8 @@ static int imm_init(int host_no)
#if defined(CONFIG_PARPORT) || defined(CONFIG_PARPORT_MODULE)
if (imm_pb_claim(host_no))
- while (imm_hosts[host_no].p_busy)
- schedule(); /* We can safe schedule here */
+ while (imm_hosts[host_no].p_busy)
+ schedule(); /* We can safe schedule here */
#endif
retv = imm_connect(host_no, 0);
@@ -770,7 +723,6 @@ static int imm_init(int host_no)
imm_pb_release(host_no);
return retv;
}
-
imm_pb_release(host_no);
return 1;
}
@@ -831,7 +783,7 @@ static int imm_completion(Scsi_Cmnd * cmd)
* If we have been running for more than a full timer tick
* then take a rest.
*/
- if (jiffies > start_jiffies + 1)
+ if (time_after(jiffies, start_jiffies + 1))
return 0;
/*
@@ -991,7 +943,7 @@ static int imm_engine(imm_struct * tmp, Scsi_Cmnd * cmd)
unsigned char l = 0, h = 0;
int retv, x;
- /* First check for any errors that may of occured
+ /* First check for any errors that may of occurred
* Here we check for internal errors
*/
if (tmp->failed)
@@ -1173,6 +1125,7 @@ int imm_biosparam(Disk * disk, kdev_t dev, int ip[])
int imm_abort(Scsi_Cmnd * cmd)
{
+ int host_no = cmd->host->unique_id;
/*
* There is no method for aborting commands since Iomega
* have tied the SCSI_MESSAGE line high in the interface
@@ -1181,12 +1134,11 @@ int imm_abort(Scsi_Cmnd * cmd)
switch (cmd->SCp.phase) {
case 0: /* Do not have access to parport */
case 1: /* Have not connected to interface */
- cmd->result = DID_ABORT;
- cmd->done(cmd);
- return SCSI_ABORT_SUCCESS;
+ imm_hosts[host_no].cur_cmd = NULL; /* Forget the problem */
+ return SUCCESS;
break;
default: /* SCSI command sent, can not abort */
- return SCSI_ABORT_BUSY;
+ return FAILED;
break;
}
}
@@ -1203,46 +1155,20 @@ void imm_reset_pulse(unsigned int base)
w_ctr(base, 0x04);
}
-int imm_reset(Scsi_Cmnd * cmd, unsigned int x)
+int imm_reset(Scsi_Cmnd * cmd)
{
int host_no = cmd->host->unique_id;
- /*
- * PHASE1:
- * Bring the interface crashing down on whatever is running
- * hopefully this will kill the request.
- * Bring back up the interface, reset the drive (and anything
- * attached for that manner)
- */
- if (cmd)
- if (cmd->SCp.phase)
- imm_disconnect(cmd->host->unique_id);
+ if (cmd->SCp.phase)
+ imm_disconnect(host_no);
+ imm_hosts[host_no].cur_cmd = NULL; /* Forget the problem */
imm_connect(host_no, CONNECT_NORMAL);
imm_reset_pulse(IMM_BASE(host_no));
- udelay(1000); /* delay for devices to settle down */
+ udelay(1000); /* device settle delay */
imm_disconnect(host_no);
- udelay(1000); /* Additional delay to allow devices to settle down */
-
- /*
- * PHASE2:
- * Sanity check for the sake of mid-level driver
- */
- if (!cmd) {
- printk("imm bus reset called for invalid command.\n");
- return SCSI_RESET_NOT_RUNNING;
- }
- /*
- * PHASE3:
- * Flag the current command as having died due to reset
- */
- imm_connect(host_no, CONNECT_NORMAL);
- imm_fail(host_no, DID_RESET);
-
- /* Since the command was already on the timer queue imm_interrupt
- * will be called shortly.
- */
- return SCSI_RESET_PENDING;
+ udelay(1000); /* device settle delay */
+ return SUCCESS;
}
static int device_check(int host_no)
@@ -1257,79 +1183,78 @@ static int device_check(int host_no)
old_mode = imm_hosts[host_no].mode;
for (loop = 0; loop < 8; loop++) {
- /* Attempt to use EPP for Test Unit Ready */
- if ((ppb & 0x0007) == 0x0000)
- imm_hosts[host_no].mode = IMM_EPP_32;
+ /* Attempt to use EPP for Test Unit Ready */
+ if ((ppb & 0x0007) == 0x0000)
+ imm_hosts[host_no].mode = IMM_EPP_32;
second_pass:
- imm_connect(host_no, CONNECT_EPP_MAYBE);
- /* Select SCSI device */
- if (!imm_select(host_no, loop)) {
- imm_disconnect(host_no);
- continue;
- }
- printk("imm: Found device at ID %i, Attempting to use %s\n", loop,
- IMM_MODE_STRING[imm_hosts[host_no].mode]);
-
- /* Send SCSI command */
- status = 1;
- w_ctr(ppb, 0x0c);
- for (l = 0; (l < 3) && (status); l++)
- status = imm_out(host_no, &cmd[l<<1], 2);
-
- if (!status) {
- imm_disconnect(host_no);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
- w_dtr(ppb, 0x40);
- w_ctr(ppb, 0x08);
- udelay(30);
- w_ctr(ppb, 0x0c);
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- if (imm_hosts[host_no].mode == IMM_EPP_32) {
- imm_hosts[host_no].mode = old_mode;
- goto second_pass;
- }
- printk("imm: Unable to establish communication, aborting driver load.\n");
- return 1;
- }
- w_ctr(ppb, 0x0c);
-
- k = 1000000; /* 1 Second */
- do {
- l = r_str(ppb);
- k--;
- udelay(1);
- } while (!(l & 0x80) && (k));
-
- l &= 0xb8;
-
- if (l != 0xb8) {
- imm_disconnect(host_no);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
+ /* Select SCSI device */
+ if (!imm_select(host_no, loop)) {
+ imm_disconnect(host_no);
+ continue;
+ }
+ printk("imm: Found device at ID %i, Attempting to use %s\n", loop,
+ IMM_MODE_STRING[imm_hosts[host_no].mode]);
+
+ /* Send SCSI command */
+ status = 1;
+ w_ctr(ppb, 0x0c);
+ for (l = 0; (l < 3) && (status); l++)
+ status = imm_out(host_no, &cmd[l << 1], 2);
+
+ if (!status) {
+ imm_disconnect(host_no);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
+ w_dtr(ppb, 0x40);
+ w_ctr(ppb, 0x08);
+ udelay(30);
+ w_ctr(ppb, 0x0c);
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ if (imm_hosts[host_no].mode == IMM_EPP_32) {
+ imm_hosts[host_no].mode = old_mode;
+ goto second_pass;
+ }
+ printk("imm: Unable to establish communication, aborting driver load.\n");
+ return 1;
+ }
+ w_ctr(ppb, 0x0c);
+
+ k = 1000000; /* 1 Second */
+ do {
+ l = r_str(ppb);
+ k--;
+ udelay(1);
+ } while (!(l & 0x80) && (k));
+
+ l &= 0xb8;
+
+ if (l != 0xb8) {
+ imm_disconnect(host_no);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
imm_reset_pulse(IMM_BASE(host_no));
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- if (imm_hosts[host_no].mode == IMM_EPP_32) {
- imm_hosts[host_no].mode = old_mode;
- goto second_pass;
- }
- printk("imm: Unable to establish communication, aborting driver load.\n");
- return 1;
- }
- imm_disconnect(host_no);
- printk("imm: Communication established with ID %i using %s\n", loop,
- IMM_MODE_STRING[imm_hosts[host_no].mode]);
- imm_connect(host_no, CONNECT_EPP_MAYBE);
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ if (imm_hosts[host_no].mode == IMM_EPP_32) {
+ imm_hosts[host_no].mode = old_mode;
+ goto second_pass;
+ }
+ printk("imm: Unable to establish communication, aborting driver load.\n");
+ return 1;
+ }
+ imm_disconnect(host_no);
+ printk("imm: Communication established with ID %i using %s\n", loop,
+ IMM_MODE_STRING[imm_hosts[host_no].mode]);
+ imm_connect(host_no, CONNECT_EPP_MAYBE);
imm_reset_pulse(IMM_BASE(host_no));
- udelay(1000);
- imm_disconnect(host_no);
- udelay(1000);
- return 0;
+ udelay(1000);
+ imm_disconnect(host_no);
+ udelay(1000);
+ return 0;
}
printk("imm: No devices found, aborting driver load.\n");
return 1;
}
-
diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h
index 2818603dd..feba4c773 100644
--- a/drivers/scsi/imm.h
+++ b/drivers/scsi/imm.h
@@ -1,7 +1,8 @@
+
/* Driver for the Iomega MatchMaker parallel port SCSI HBA embedded in
* the Iomega ZIP Plus drive
*
- * (c) 1998 David Campbell campbell@torque.net
+ * (c) 1998 David Campbell campbell@torque.net
*
* Please note that I live in Perth, Western Australia. GMT+0800
*/
@@ -9,13 +10,13 @@
#ifndef _IMM_H
#define _IMM_H
-#define IMM_VERSION "2.00"
+#define IMM_VERSION "2.03 (for Linux 2.0.0)"
/*
* 10 Apr 1998 (Good Friday) - Received EN144302 by email from Iomega.
* Scarry thing is the level of support from one of their managers.
* The onus is now on us (the developers) to shut up and start coding.
- * 11Apr98 [ 0.10 ]
+ * 11Apr98 [ 0.10 ]
*
* --- SNIP ---
*
@@ -24,39 +25,45 @@
* Removing "Phase" debug messages.
*
* PS: Took four hours of coding after I bought a drive.
- * ANZAC Day (Aus "War Veterans Holiday") 25Apr98 [ 0.14 ]
+ * ANZAC Day (Aus "War Veterans Holiday") 25Apr98 [ 0.14 ]
*
* Ten minutes later after a few fixes.... (LITERALLY!!!)
* Have mounted disk, copied file, dismounted disk, remount disk, diff file
* ----- It actually works!!! -----
- * 25Apr98 [ 0.15 ]
+ * 25Apr98 [ 0.15 ]
*
* Twenty minutes of mucking around, rearanged the IEEE negotiate mechanism.
* Now have byte mode working (only EPP and ECP to go now... :=)
- * 26Apr98 [ 0.16 ]
+ * 26Apr98 [ 0.16 ]
*
* Thirty minutes of further coding results in EPP working on my machine.
- * 27Apr98 [ 0.17 ]
+ * 27Apr98 [ 0.17 ]
*
* Due to work commitments and inability to get a "true" ECP mode functioning
* I have decided to code the parport support into imm.
- * 09Jun98 [ 0.18 ]
+ * 09Jun98 [ 0.18 ]
*
* Driver is now out of beta testing.
* Support for parport has been added.
* Now distributed with the ppa driver.
- * 12Jun98 [ 2.00 ]
+ * 12Jun98 [ 2.00 ]
*
* Err.. It appears that imm-2.00 was broken....
- * 18Jun98 [ 2.01 ]
+ * 18Jun98 [ 2.01 ]
*
* Patch applied to sync this against the Linux 2.1.x kernel code
* Included qboot_zip.sh
- * 21Jun98 [ 2.02 ]
+ * 21Jun98 [ 2.02 ]
+ *
+ * Other clean ups include the follow changes:
+ * CONFIG_SCSI_PPA_HAVE_PEDANTIC => CONFIG_SCSI_IZIP_EPP16
+ * added CONFIG_SCSI_IZIP_SLOW_CTR option
+ * [2.03]
*/
/* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
#ifdef IMM_CODE
+#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -92,7 +99,11 @@ static char *IMM_MODE_STRING[] =
"PS/2",
"EPP 8 bit",
"EPP 16 bit",
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ "EPP 16 bit",
+#else
"EPP 32 bit",
+#endif
"Unknown"};
/* This is a global option */
@@ -110,21 +121,24 @@ int imm_sg = SG_ALL; /* enable/disable scatter-gather. */
#define CONNECT_EPP_MAYBE 1
#define CONNECT_NORMAL 0
-#define inb_x inb
-#define r_dtr(x) (unsigned char)inb_x((x))
-#define r_str(x) (unsigned char)inb_x((x)+1)
-#define r_ctr(x) (unsigned char)inb_x((x)+2)
-#define r_epp(x) (unsigned char)inb_x((x)+4)
-#define r_fifo(x) (unsigned char)inb_x((x)+0x400)
-#define r_ecr(x) (unsigned char)inb_x((x)+0x402)
-
-#define outb_x outb
-#define w_dtr(x,y) outb_x(y, (x))
-#define w_str(x,y) outb_x(y, (x)+1)
-#define w_ctr(x,y) outb_x(y, (x)+2)
-#define w_epp(x,y) outb_x(y, (x)+4)
-#define w_fifo(x,y) outb_x(y, (x)+0x400)
-#define w_ecr(x,y) outb_x(y, (x)+0x402)
+#define r_dtr(x) (unsigned char)inb((x))
+#define r_str(x) (unsigned char)inb((x)+1)
+#define r_ctr(x) (unsigned char)inb((x)+2)
+#define r_epp(x) (unsigned char)inb((x)+4)
+#define r_fifo(x) (unsigned char)inb((x)+0x400)
+#define r_ecr(x) (unsigned char)inb((x)+0x402)
+
+#define w_dtr(x,y) outb(y, (x))
+#define w_str(x,y) outb(y, (x)+1)
+#define w_epp(x,y) outb(y, (x)+4)
+#define w_fifo(x,y) outb(y, (x)+0x400)
+#define w_ecr(x,y) outb(y, (x)+0x402)
+
+#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
+#define w_ctr(x,y) outb_p(y, (x)+2)
+#else
+#define w_ctr(x,y) outb(y, (x)+2)
+#endif
static int imm_engine(imm_struct *, Scsi_Cmnd *);
static int imm_in(int, char *, int);
@@ -144,23 +158,25 @@ const char *imm_info(struct Scsi_Host *);
int imm_command(Scsi_Cmnd *);
int imm_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
int imm_abort(Scsi_Cmnd *);
-int imm_reset(Scsi_Cmnd *, unsigned int);
+int imm_reset(Scsi_Cmnd *);
int imm_proc_info(char *, char **, off_t, int, int, int);
int imm_biosparam(Disk *, kdev_t, int *);
-#define IMM { proc_dir: &proc_scsi_imm, \
- proc_info: imm_proc_info, \
- name: "Iomega ZIP Plus drive", \
- detect: imm_detect, \
- release: imm_release, \
- command: imm_command, \
- queuecommand: imm_queuecommand, \
- abort: imm_abort, \
- reset: imm_reset, \
- bios_param: imm_biosparam, \
- this_id: 7, \
- sg_tablesize: SG_ALL, \
- cmd_per_lun: 1, \
- use_clustering: ENABLE_CLUSTERING \
+#define IMM { proc_dir: &proc_scsi_imm, \
+ proc_info: imm_proc_info, \
+ name: "Iomega VPI2 (imm) interface",\
+ detect: imm_detect, \
+ release: imm_release, \
+ command: imm_command, \
+ queuecommand: imm_queuecommand, \
+ eh_abort_handler: imm_abort, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: imm_reset, \
+ eh_host_reset_handler: imm_reset, \
+ bios_param: imm_biosparam, \
+ this_id: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: 1, \
+ use_clustering: ENABLE_CLUSTERING \
}
#endif /* _IMM_H */
diff --git a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c
new file mode 100644
index 000000000..6dba96b62
--- /dev/null
+++ b/drivers/scsi/ini9100u.c
@@ -0,0 +1,1147 @@
+/**************************************************************************
+ * Initio 9100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 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 name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
+ *
+ *************************************************************************
+ *
+ * DESCRIPTION:
+ *
+ * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host
+ * adapters
+ *
+ * 08/06/97 hc - v1.01h
+ * - Support inic-940 and inic-935
+ * 09/26/97 hc - v1.01i
+ * - Make correction from J.W. Schultz suggestion
+ * 10/13/97 hc - Support reset function
+ * 10/21/97 hc - v1.01j
+ * - Support 32 LUN (SCSI 3)
+ * 01/14/98 hc - v1.01k
+ * - Fix memory allocation problem
+ * 03/04/98 hc - v1.01l
+ * - Fix tape rewind which will hang the system problem
+ * - Set can_queue to tul_num_scb
+ * 06/25/98 hc - v1.01m
+ * - Get it work for kernel version >= 2.1.75
+ * - Dynamic assign SCSI bus reset holding time in init_tulip()
+ * 07/02/98 hc - v1.01n
+ * - Support 0002134A
+ * 08/07/98 hc - v1.01o
+ * - Change the tul_abort_srb routine to use scsi_done. <01>
+ * 09/07/98 hl - v1.02
+ * - Change the INI9100U define and proc_dir_entry to
+ * reflect the newer Kernel 2.1.118, but the v1.o1o
+ * should work with Kernel 2.1.118.
+ * 09/20/98 wh - v1.02a
+ * - Support Abort command.
+ * - Handle reset routine.
+ * 09/21/98 hl - v1.03
+ * - remove comments.
+ * 12/09/98 bv - v1.03a
+ * - Removed unused code
+ * 12/13/98 bv - v1.03b
+ * - Remove cli() locking for kernels >= 2.1.95. This uses
+ * spinlocks to serialize access to the pSRB_head and
+ * pSRB_tail members of the HCS structure.
+ * 09/01/99 bv - v1.03d
+ * - Fixed a deadlock problem in SMP.
+ **************************************************************************/
+
+#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+#include <stdarg.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
+#include <linux/bios32.h>
+#endif
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
+#include <linux/init.h>
+#endif
+#include <linux/blk.h>
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+#include "ini9100u.h"
+#include <linux/stat.h>
+#include <linux/malloc.h>
+#include <linux/config.h>
+
+#else
+
+#include <linux/kernel.h>
+#include <linux/head.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include "../block/blk.h"
+#include "scsi.h"
+#include "sd.h"
+#include "hosts.h"
+#include <linux/malloc.h>
+#include "ini9100u.h"
+#endif
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+#endif
+
+#ifdef DEBUG_i91u
+unsigned int i91u_debug = DEBUG_DEFAULT;
+#endif
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = INI9100U;
+#include "scsi_module.c"
+#endif
+
+char *i91uCopyright = "Copyright (C) 1996-98";
+char *i91uInitioName = "by Initio Corporation";
+char *i91uProductName = "INI-9X00U/UW";
+char *i91uVersion = "v1.03d";
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+struct proc_dir_entry proc_scsi_ini9100u =
+{
+ PROC_SCSI_INI9100U, 7, "INI9100U",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2,
+ 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+#endif
+
+#define TULSZ(sz) (sizeof(sz) / sizeof(sz[0]))
+#define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+
+/* set by i91_setup according to the command line */
+static int setup_called = 0;
+
+static int tul_num_ch = 4; /* Maximum 4 adapters */
+static int tul_num_scb;
+static int tul_tag_enable = 1;
+static SCB *tul_scb;
+
+#ifdef DEBUG_i91u
+static int setup_debug = 0;
+#endif
+
+static char *setup_str = (char *) NULL;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr0(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr1(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr2(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr3(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr4(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr5(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr6(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr7(int irq, void *dev_id, struct pt_regs *);
+#else
+static void i91u_intr0(int irq, struct pt_regs *);
+static void i91u_intr1(int irq, struct pt_regs *);
+static void i91u_intr2(int irq, struct pt_regs *);
+static void i91u_intr3(int irq, struct pt_regs *);
+static void i91u_intr4(int irq, struct pt_regs *);
+static void i91u_intr5(int irq, struct pt_regs *);
+static void i91u_intr6(int irq, struct pt_regs *);
+static void i91u_intr7(int irq, struct pt_regs *);
+#endif
+
+static void i91u_panic(char *msg);
+
+static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
+
+ /* ---- EXTERNAL FUNCTIONS ---- */
+ /* Get total number of adapters */
+extern void init_i91uAdapter_table(void);
+extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE);
+extern int tul_ReturnNumberOfAdapters(void);
+extern void get_tulipPCIConfig(HCS * pHCB, int iChannel_index);
+extern int init_tulip(HCS * pHCB, SCB * pSCB, int tul_num_scb, BYTE * pbBiosAdr, int reset_time);
+extern SCB *tul_alloc_scb(HCS * pHCB);
+extern int tul_abort_srb(HCS * pHCB, Scsi_Cmnd * pSRB);
+extern void tul_exec_scb(HCS * pHCB, SCB * pSCB);
+extern void tul_release_scb(HCS * pHCB, SCB * pSCB);
+extern void tul_stop_bm(HCS * pHCB);
+extern int tul_reset_scsi(HCS * pCurHcb, int seconds);
+extern int tul_isr(HCS * pHCB);
+extern int tul_reset(HCS * pHCB, Scsi_Cmnd * pSRB, unsigned char target);
+extern int tul_reset_scsi_bus(HCS * pCurHcb);
+extern int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags);
+ /* ---- EXTERNAL VARIABLES ---- */
+extern HCS tul_hcs[];
+
+struct id {
+ int vendor_id;
+ int device_id;
+};
+
+const struct id id_table[] = {
+ { INI_VENDOR_ID, I950_DEVICE_ID },
+ { INI_VENDOR_ID, I940_DEVICE_ID },
+ { INI_VENDOR_ID, I935_DEVICE_ID },
+ { INI_VENDOR_ID, 0x0002 },
+ { DMX_VENDOR_ID, 0x0002 },
+};
+
+/*
+ * queue services:
+ */
+/*****************************************************************************
+ Function name : i91uAppendSRBToQueue
+ Description : This function will push current request into save list
+ Input : pSRB - Pointer to SCSI request block.
+ pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : None.
+*****************************************************************************/
+static void i91uAppendSRBToQueue(HCS * pHCB, Scsi_Cmnd * pSRB)
+{
+ ULONG flags;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+
+ pSRB->next = NULL; /* Pointer to next */
+
+ if (pHCB->pSRB_head == NULL)
+ pHCB->pSRB_head = pSRB;
+ else
+ pHCB->pSRB_tail->next = pSRB; /* Pointer to next */
+ pHCB->pSRB_tail = pSRB;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
+#else
+ restore_flags(flags);
+#endif
+ return;
+}
+
+/*****************************************************************************
+ Function name : i91uPopSRBFromQueue
+ Description : This function will pop current request from save list
+ Input : pHCB - Pointer to host adapter structure
+ Output : None.
+ Return : pSRB - Pointer to SCSI request block.
+*****************************************************************************/
+static Scsi_Cmnd *i91uPopSRBFromQueue(HCS * pHCB)
+{
+ Scsi_Cmnd *pSRB;
+ ULONG flags;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&(pHCB->pSRB_lock), flags);
+#else
+ save_flags(flags);
+ cli();
+#endif
+
+ if ((pSRB = pHCB->pSRB_head) != NULL) {
+ pHCB->pSRB_head = pHCB->pSRB_head->next;
+ pSRB->next = NULL;
+ }
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&(pHCB->pSRB_lock), flags);
+#else
+ restore_flags(flags);
+#endif
+
+ return (pSRB);
+}
+
+/* called from init/main.c */
+
+void i91u_setup(char *str, int *ints)
+{
+ if (setup_called)
+ i91u_panic("i91u: i91u_setup called twice.\n");
+
+ setup_called = ints[0];
+ setup_str = str;
+
+#ifdef DEBUG_i91u
+ setup_debug = ints[0] >= 1 ? ints[1] : DEBUG_DEFAULT;
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
+int tul_NewReturnNumberOfAdapters(void)
+{
+ struct pci_dev *pDev = NULL; /* Start from none */
+ int iAdapters = 0;
+ long dRegValue;
+ WORD wBIOS;
+ const int iNumIdEntries = sizeof(id_table)/sizeof(id_table[0]);
+ int i = 0;
+
+ init_i91uAdapter_table();
+
+ for (i=0; i < iNumIdEntries; i++) {
+ struct id curId = id_table[i];
+ while ((pDev = pci_find_device(curId.vendor_id, curId.device_id, pDev)) != NULL) {
+ pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
+ wBIOS = (UWORD) (dRegValue & 0xFF);
+ if (((dRegValue & 0xFF00) >> 8) == 0xFF)
+ dRegValue = 0;
+ wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
+ if (Addi91u_into_Adapter_table(wBIOS,
+ (pDev->base_address[0] & 0xFFFE),
+ pDev->irq,
+ pDev->bus->number,
+ (pDev->devfn >> 3)
+ ) == 0)
+ iAdapters++;
+ }
+ }
+
+ return (iAdapters);
+}
+
+#else /* <01> */
+
+/*****************************************************************************
+ Function name : tul_ReturnNumberOfAdapters
+ Description : This function will scan PCI bus to get all Orchid card
+ Input : None.
+ Output : None.
+ Return : SUCCESSFUL - Successful scan
+ ohterwise - No drives founded
+*****************************************************************************/
+int tul_ReturnNumberOfAdapters(void)
+{
+ unsigned int i, iAdapters;
+ unsigned int dRegValue;
+ unsigned short command;
+ WORD wBIOS, wBASE;
+ BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum;
+ struct {
+ unsigned short vendor_id;
+ unsigned short device_id;
+ } const i91u_pci_devices[] =
+ {
+ {INI_VENDOR_ID, I935_DEVICE_ID},
+ {INI_VENDOR_ID, I940_DEVICE_ID},
+ {INI_VENDOR_ID, I950_DEVICE_ID},
+ {INI_VENDOR_ID, I920_DEVICE_ID}
+ };
+
+
+ iAdapters = 0;
+ /*
+ * PCI-bus probe.
+ */
+ if (pcibios_present()) {
+#ifdef MMAPIO
+ unsigned long page_offset, base;
+#endif
+
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+ struct pci_dev *pdev = NULL;
+#else
+ int index;
+ unsigned char pci_bus, pci_devfn;
+#endif
+
+ bPCIBusNum = 0;
+ bPCIDeviceNum = 0;
+ init_i91uAdapter_table();
+ for (i = 0; i < TULSZ(i91u_pci_devices); i++) {
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+ pdev = NULL;
+ while ((pdev = pci_find_device(i91u_pci_devices[i].vendor_id,
+ i91u_pci_devices[i].device_id,
+ pdev)))
+#else
+ index = 0;
+ while (!(pcibios_find_device(i91u_pci_devices[i].vendor_id,
+ i91u_pci_devices[i].device_id,
+ index++, &pci_bus, &pci_devfn)))
+#endif
+ {
+ if (i == 0) {
+ /*
+ printk("i91u: The RAID controller is not supported by\n");
+ printk("i91u: this driver, we are ignoring it.\n");
+ */
+ } else {
+ /*
+ * Read sundry information from PCI BIOS.
+ */
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+ bPCIBusNum = pdev->bus->number;
+ bPCIDeviceNum = pdev->devfn;
+ dRegValue = pdev->base_address[0];
+ if (dRegValue == -1) { /* Check return code */
+ printk("\n\ri91u: tulip read configuration error.\n");
+ return (0); /* Read configuration space error */
+ }
+ /* <02> read from base address + 0x50 offset to get the wBIOS balue. */
+ wBASE = (WORD) dRegValue;
+
+ /* Now read the interrupt line */
+ dRegValue = pdev->irq;
+ bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */
+ pci_read_config_word(pdev, PCI_COMMAND, &command);
+ pci_write_config_word(pdev, PCI_COMMAND,
+ command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+
+#else
+ bPCIBusNum = pci_bus;
+ bPCIDeviceNum = pci_devfn;
+ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0,
+ &dRegValue);
+ if (dRegValue == -1) { /* Check return code */
+ printk("\n\ri91u: tulip read configuration error.\n");
+ return (0); /* Read configuration space error */
+ }
+ /* <02> read from base address + 0x50 offset to get the wBIOS balue. */
+ wBASE = (WORD) dRegValue;
+
+ /* Now read the interrupt line */
+ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_INTERRUPT_LINE,
+ &dRegValue);
+ bInterrupt = dRegValue & 0xFF; /* Assign interrupt line */
+ pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
+ pcibios_write_config_word(pci_bus, pci_devfn, PCI_COMMAND,
+ command | PCI_COMMAND_MASTER | PCI_COMMAND_IO);
+#endif
+ wBASE &= PCI_BASE_ADDRESS_IO_MASK;
+ wBIOS = TUL_RDWORD(wBASE, 0x50);
+
+#ifdef MMAPIO
+ base = wBASE & PAGE_MASK;
+ page_offset = wBASE - base;
+
+ /*
+ * replace the next line with this one if you are using 2.1.x:
+ * temp_p->maddr = ioremap(base, page_offset + 256);
+ */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,0)
+ wBASE = ioremap(base, page_offset + 256);
+#else
+ wBASE = (WORD) vremap(base, page_offset + 256);
+#endif
+ if (wBASE) {
+ wBASE += page_offset;
+ }
+#endif
+
+ if (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum,
+ bPCIDeviceNum) == 0x0)
+ iAdapters++;
+ }
+ } /* while(pdev=....) */
+ } /* for PCI_DEVICES */
+ } /* PCI BIOS present */
+ return (iAdapters);
+}
+#endif
+
+int i91u_detect(Scsi_Host_Template * tpnt)
+{
+ SCB *pSCB;
+ HCS *pHCB;
+ struct Scsi_Host *hreg;
+ unsigned long i; /* 01/14/98 */
+ int ok = 0, iAdapters;
+ ULONG dBiosAdr;
+ BYTE *pbBiosAdr;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ tpnt->proc_dir = &proc_scsi_ini9100u;
+#endif
+
+ if (setup_called) { /* Setup by i91u_setup */
+ printk("i91u: processing commandline: ");
+
+#ifdef DEBUG_i91u
+ if (setup_called > 1) {
+ printk("\ni91u: %s\n", setup_str);
+ printk("i91u: usage: i91u[=<DEBUG>]\n");
+ i91u_panic("i91u panics in line %d", __LINE__);
+ }
+ i91u_debug = setup_debug;
+#endif
+ }
+ /* Get total number of adapters in the motherboard */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
+#ifdef CONFIG_PCI
+ iAdapters = tul_NewReturnNumberOfAdapters();
+#else
+ iAdapters = tul_ReturnNumberOfAdapters();
+#endif
+#else
+ iAdapters = tul_ReturnNumberOfAdapters();
+#endif
+
+ if (iAdapters == 0) /* If no tulip founded, return */
+ return (0);
+
+ tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters;
+ /* Update actually channel number */
+ if (tul_tag_enable) { /* 1.01i */
+ tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE;
+ } else {
+ tul_num_scb = MAX_TARGETS + 3; /* 1-tape, 1-CD_ROM, 1- extra */
+ } /* Update actually SCBs per adapter */
+
+ /* Get total memory needed for HCS */
+ i = tul_num_ch * sizeof(HCS);
+ memset((unsigned char *) &tul_hcs[0], 0, i); /* Initialize tul_hcs 0 */
+ /* Get total memory needed for SCB */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
+ i = tul_num_ch * tul_num_scb * sizeof(SCB);
+ if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
+ break;
+ }
+#else
+ i = tul_num_ch * tul_num_scb * sizeof(SCB);
+ tul_scb = (SCB *) scsi_init_malloc(i, GFP_ATOMIC | GFP_DMA);
+#endif
+ if (tul_scb == NULL) {
+ printk("i91u: SCB memory allocation error\n");
+ return (0);
+ }
+ memset((unsigned char *) tul_scb, 0, i);
+
+ pSCB = tul_scb;
+ for (i = 0; i < tul_num_ch * tul_num_scb; i++, pSCB++) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pSCB->SCB_SGPAddr = (U32) VIRT_TO_BUS(&pSCB->SCB_SGList[0]);
+#else
+ pSCB->SCB_SGPAddr = (U32) (&pSCB->SCB_SGList[0]);
+#endif
+ }
+
+ for (i = 0, pHCB = &tul_hcs[0]; /* Get pointer for control block */
+ i < tul_num_ch;
+ i++, pHCB++) {
+ pHCB->pSRB_head = NULL; /* Initial SRB save queue */
+ pHCB->pSRB_tail = NULL; /* Initial SRB save queue */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ pHCB->pSRB_lock = SPIN_LOCK_UNLOCKED; /* SRB save queue lock */
+#endif
+ request_region(pHCB->HCS_Base, 0x100, "i91u"); /* Register */
+
+ get_tulipPCIConfig(pHCB, i);
+
+ dBiosAdr = pHCB->HCS_BIOS;
+ dBiosAdr = (dBiosAdr << 4);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pbBiosAdr = phys_to_virt(dBiosAdr);
+#endif
+
+ init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
+ pHCB->HCS_Index = i; /* 7/29/98 */
+ hreg = scsi_register(tpnt, sizeof(HCS));
+ hreg->io_port = pHCB->HCS_Base;
+ hreg->n_io_port = 0xff;
+ hreg->can_queue = tul_num_scb; /* 03/05/98 */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ hreg->unique_id = pHCB->HCS_Base;
+ hreg->max_id = pHCB->HCS_MaxTar;
+#endif
+ hreg->max_lun = 32; /* 10/21/97 */
+ hreg->irq = pHCB->HCS_Intr;
+ hreg->this_id = pHCB->HCS_SCSI_ID; /* Assign HCS index */
+ hreg->base = (UCHAR *) pHCB;
+ hreg->sg_tablesize = TOTAL_SG_ENTRY; /* Maximun support is 32 */
+
+ /* Initial tulip chip */
+ switch (i) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ case 0:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 1:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 2:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 3:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 4:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 5:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 6:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ case 7:
+ ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+ break;
+ default:
+ i91u_panic("i91u: Too many host adapters\n");
+ break;
+ }
+ if (ok < 0) {
+ if (ok == -EINVAL) {
+ printk("i91u: bad IRQ %d.\n", pHCB->HCS_Intr);
+ printk(" Contact author.\n");
+ } else if (ok == -EBUSY)
+ printk("i91u: IRQ %d already in use. Configure another.\n",
+ pHCB->HCS_Intr);
+ else {
+ printk("\ni91u: Unexpected error code on requesting IRQ %d.\n",
+ pHCB->HCS_Intr);
+ printk(" Contact author.\n");
+ }
+ i91u_panic("i91u: driver needs an IRQ.\n");
+ }
+#endif
+ }
+
+ tpnt->this_id = -1;
+ tpnt->can_queue = 1;
+
+ return 1;
+}
+
+static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt)
+{ /* Create corresponding SCB */
+ struct scatterlist *pSrbSG;
+ SG *pSG; /* Pointer to SG list */
+ int i;
+ long TotalLen;
+
+ pSCB->SCB_Post = i91uSCBPost; /* i91u's callback routine */
+ pSCB->SCB_Srb = SCpnt;
+ pSCB->SCB_Opcode = ExecSCSI;
+ pSCB->SCB_Flags = SCF_POST; /* After SCSI done, call post routine */
+ pSCB->SCB_Target = SCpnt->target;
+ pSCB->SCB_Lun = SCpnt->lun;
+ pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW;
+ pSCB->SCB_Flags |= SCF_SENSE; /* Turn on auto request sense */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pSCB->SCB_SensePtr = (U32) VIRT_TO_BUS(SCpnt->sense_buffer);
+#else
+ pSCB->SCB_SensePtr = (U32) (SCpnt->sense_buffer);
+#endif
+
+ pSCB->SCB_SenseLen = SENSE_SIZE;
+
+ pSCB->SCB_CDBLen = SCpnt->cmd_len;
+ pSCB->SCB_HaStat = 0;
+ pSCB->SCB_TaStat = 0;
+ memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len);
+
+ if (SCpnt->device->tagged_supported) { /* Tag Support */
+ pSCB->SCB_TagMsg = SIMPLE_QUEUE_TAG; /* Do simple tag only */
+ } else {
+ pSCB->SCB_TagMsg = 0; /* No tag support */
+ }
+
+ if (SCpnt->use_sg) {
+ pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
+ if (SCpnt->use_sg == 1) { /* If only one entry in the list *//* treat it as regular I/O */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address);
+#else
+ pSCB->SCB_BufPtr = (U32) (pSrbSG->address);
+#endif
+ TotalLen = pSrbSG->length;
+ pSCB->SCB_SGLen = 0;
+ } else { /* Assign SG physical address */
+ pSCB->SCB_BufPtr = pSCB->SCB_SGPAddr;
+ pSCB->SCB_Flags |= SCF_SG; /* Turn on SG list flag */
+ for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0]; /* 1.01g */
+ i < SCpnt->use_sg;
+ i++, pSG++, pSrbSG++) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pSG->SG_Ptr = (U32) VIRT_TO_BUS(pSrbSG->address);
+#else
+ pSG->SG_Ptr = (U32) (pSrbSG->address);
+#endif
+ TotalLen += pSG->SG_Len = pSrbSG->length;
+ }
+ pSCB->SCB_SGLen = i;
+ }
+ pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
+ TotalLen : SCpnt->request_bufflen;
+ } else { /* Non SG */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+ pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(SCpnt->request_buffer);
+#else
+ pSCB->SCB_BufPtr = (U32) (SCpnt->request_buffer);
+#endif
+ pSCB->SCB_BufLen = SCpnt->request_bufflen;
+ pSCB->SCB_SGLen = 0;
+ }
+
+ return;
+}
+
+/*
+ * Queue a command and setup interrupts for a free bus.
+ */
+int i91u_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+{
+ register SCB *pSCB;
+ HCS *pHCB; /* Point to Host adapter control block */
+
+ if (SCpnt->lun > 16) { /* 07/22/98 */
+
+ SCpnt->result = (DID_TIME_OUT << 16);
+ done(SCpnt); /* Notify system DONE */
+ return (0);
+ }
+ pHCB = (HCS *) SCpnt->host->base;
+
+ SCpnt->scsi_done = done;
+ /* Get free SCSI control block */
+ if ((pSCB = tul_alloc_scb(pHCB)) == NULL) {
+ i91uAppendSRBToQueue(pHCB, SCpnt); /* Buffer this request */
+ return (0);
+ }
+ i91uBuildSCB(pHCB, pSCB, SCpnt);
+ tul_exec_scb(pHCB, pSCB); /* Start execute SCB */
+ return (0);
+}
+
+/*
+ * We only support command in interrupt-driven fashion
+ */
+int i91u_command(Scsi_Cmnd * SCpnt)
+{
+ printk("i91u: interrupt driven driver; use i91u_queue()\n");
+ return -1;
+}
+
+/*
+ * Abort a queued command
+ * (commands that are on the bus can't be aborted easily)
+ */
+int i91u_abort(Scsi_Cmnd * SCpnt)
+{
+ HCS *pHCB;
+
+ pHCB = (HCS *) SCpnt->host->base;
+ return tul_abort_srb(pHCB, SCpnt);
+}
+
+/*
+ * Reset registers, reset a hanging bus and
+ * kill active and disconnected commands for target w/o soft reset
+ */
+int i91u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+{ /* I need Host Control Block Information */
+ HCS *pHCB;
+
+ pHCB = (HCS *) SCpnt->host->base;
+
+ if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
+ return tul_reset_scsi_bus(pHCB);
+ else
+ return tul_device_reset(pHCB, (ULONG) SCpnt, SCpnt->target, reset_flags);
+}
+
+/*
+ * Return the "logical geometry"
+ */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+int i91u_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
+#else
+int i91u_biosparam(Scsi_Disk * disk, int dev, int *info_array)
+#endif
+{
+ HCS *pHcb; /* Point to Host adapter control block */
+ TCS *pTcb;
+
+ pHcb = (HCS *) disk->device->host->base;
+ pTcb = &pHcb->HCS_Tcs[disk->device->id];
+
+ if (pTcb->TCS_DrvHead) {
+ info_array[0] = pTcb->TCS_DrvHead;
+ info_array[1] = pTcb->TCS_DrvSector;
+ info_array[2] = disk->capacity / pTcb->TCS_DrvHead / pTcb->TCS_DrvSector;
+ } else {
+ if (pTcb->TCS_DrvFlags & TCF_DRV_255_63) {
+ info_array[0] = 255;
+ info_array[1] = 63;
+ info_array[2] = disk->capacity / 255 / 63;
+ } else {
+ info_array[0] = 64;
+ info_array[1] = 32;
+ info_array[2] = disk->capacity >> 11;
+ }
+ }
+
+#if defined(DEBUG_BIOSPARAM)
+ if (i91u_debug & debug_biosparam) {
+ printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
+ info_array[0], info_array[1], info_array[2]);
+ printk("WARNING: check, if the bios geometry is correct.\n");
+ }
+#endif
+
+ return 0;
+}
+
+/*****************************************************************************
+ Function name : i91uSCBPost
+ Description : This is callback routine be called when tulip finish one
+ SCSI command.
+ Input : pHCB - Pointer to host adapter control block.
+ pSCB - Pointer to SCSI control block.
+ Output : None.
+ Return : None.
+*****************************************************************************/
+static void i91uSCBPost(BYTE * pHcb, BYTE * pScb)
+{
+ Scsi_Cmnd *pSRB; /* Pointer to SCSI request block */
+ HCS *pHCB;
+ SCB *pSCB;
+
+ pHCB = (HCS *) pHcb;
+ pSCB = (SCB *) pScb;
+ if ((pSRB = pSCB->SCB_Srb) == 0) {
+ printk("i91uSCBPost: SRB pointer is empty\n");
+
+ tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */
+ return;
+ }
+ switch (pSCB->SCB_HaStat) {
+ case 0x0:
+ case 0xa: /* Linked command complete without error and linked normally */
+ case 0xb: /* Linked command complete without error interrupt generated */
+ pSCB->SCB_HaStat = 0;
+ break;
+
+ case 0x11: /* Selection time out-The initiator selection or target
+ reselection was not complete within the SCSI Time out period */
+ pSCB->SCB_HaStat = DID_TIME_OUT;
+ break;
+
+ case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
+ phase sequence was requested by the target. The host adapter
+ will generate a SCSI Reset Condition, notifying the host with
+ a SCRD interrupt */
+ pSCB->SCB_HaStat = DID_RESET;
+ break;
+
+ case 0x1a: /* SCB Aborted. 07/21/98 */
+ pSCB->SCB_HaStat = DID_ABORT;
+ break;
+
+ case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
+ than was allocated by the Data Length field or the sum of the
+ Scatter / Gather Data Length fields. */
+ case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
+ case 0x16: /* Invalid SCB Operation Code. */
+
+ default:
+ printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
+ pSCB->SCB_HaStat = DID_ERROR; /* Couldn't find any better */
+ break;
+ }
+
+ pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
+
+ if (pSRB == NULL) {
+ printk("pSRB is NULL\n");
+ }
+ pSRB->scsi_done(pSRB); /* Notify system DONE */
+ if ((pSRB = i91uPopSRBFromQueue(pHCB)) != NULL)
+ /* Find the next pending SRB */
+ { /* Assume resend will success */
+ /* Reuse old SCB */
+ i91uBuildSCB(pHCB, pSCB, pSRB); /* Create corresponding SCB */
+
+ tul_exec_scb(pHCB, pSCB); /* Start execute SCB */
+ } else { /* No Pending SRB */
+ tul_release_scb(pHCB, pSCB); /* Release SCB for current channel */
+ }
+ return;
+}
+
+/*
+ * Interrupts handler (main routine of the driver)
+ */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr0(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[0].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[0]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr1(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[1].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[1]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr2(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[2].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[2]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr3(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[3].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[3]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr4(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[4].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[4]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr5(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[5].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[5]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr6(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[6].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[6]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr7(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ unsigned long flags;
+#endif
+
+ if (tul_hcs[7].HCS_Intr != irqno)
+ return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+ tul_isr(&tul_hcs[7]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+/*
+ * Dump the current driver status and panic...
+ */
+static void i91u_panic(char *msg)
+{
+ printk("\ni91u_panic: %s\n", msg);
+ panic("i91u panic");
+}
diff --git a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h
new file mode 100644
index 000000000..fa2c6c537
--- /dev/null
+++ b/drivers/scsi/ini9100u.h
@@ -0,0 +1,335 @@
+/**************************************************************************
+ * Initio 9100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 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 name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Where this Software is combined with software released under the terms of
+ * the GNU Public License ("GPL") and the terms of the GPL would require the
+ * combined work to also be released under the terms of the GPL, the terms
+ * and conditions of this License will apply in addition to those of the
+ * GPL with the exception of any terms or conditions of this License that
+ * conflict with, or are expressly prohibited by, the GPL.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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.
+ *
+ *************************************************************************
+ *
+ * Module: ini9100u.h
+ * Description: INI-9100U/UW LINUX device driver header
+ * Revision History:
+ * 06/18/96 Harry Chen, Initial Version 1.00A (Beta)
+ * 06/23/98 hc - v1.01k
+ * - Get it work for kernel version >= 2.1.75
+ * 12/09/98 bv - v1.03a
+ * - Removed unused code
+ * 12/13/98 bv - v1.03b
+ * - Add spinlocks to HCS structure.
+*******************************************************************************/
+
+#ifndef CVT_LINUX_VERSION
+#define CVT_LINUX_VERSION(V,P,S) (((V) * 65536) + ((P) * 256) + (S))
+#endif
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#include "sd.h"
+
+extern int i91u_detect(Scsi_Host_Template *);
+extern int i91u_command(Scsi_Cmnd *);
+extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+extern int i91u_abort(Scsi_Cmnd *);
+extern int i91u_reset(Scsi_Cmnd *, unsigned int);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0)
+extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
+extern struct proc_dir_entry proc_scsi_ini9100u;
+#else
+extern int i91u_biosparam(Disk *, int, int *); /*for linux v1.13 */
+#endif
+
+#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03d"
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0)
+#define INI9100U { \
+ NULL, \
+ NULL, \
+ i91u_REVID, \
+ i91u_detect, \
+ NULL, \
+ NULL, \
+ i91u_command, \
+ i91u_queue, \
+ i91u_abort, \
+ i91u_reset, \
+ NULL, \
+ i91u_biosparam, \
+ 1, \
+ 7, \
+ SG_ALL, \
+ 1, \
+ 0, \
+ 0, \
+ ENABLE_CLUSTERING \
+}
+#else
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75)
+#define INI9100U { \
+ NULL, \
+ NULL, \
+ &proc_scsi_ini9100u, \
+ NULL, \
+ i91u_REVID, \
+ i91u_detect, \
+ NULL, \
+ NULL, \
+ i91u_command, \
+ i91u_queue, \
+ i91u_abort, \
+ i91u_reset, \
+ NULL, \
+ i91u_biosparam, \
+ 1, \
+ 7, \
+ SG_ALL, \
+ 1, \
+ 0, \
+ 0, \
+ ENABLE_CLUSTERING \
+}
+#else /* Version >= 2.1.75 */
+#define INI9100U { \
+ next: NULL, \
+ module: NULL, \
+ proc_dir: &proc_scsi_ini9100u, \
+ proc_info: NULL, \
+ name: i91u_REVID, \
+ detect: i91u_detect, \
+ release: NULL, \
+ info: NULL, \
+ command: i91u_command, \
+ queuecommand: i91u_queue, \
+ eh_strategy_handler: NULL, \
+ eh_abort_handler: NULL, \
+ eh_device_reset_handler: NULL, \
+ eh_bus_reset_handler: NULL, \
+ eh_host_reset_handler: NULL, \
+ abort: i91u_abort, \
+ reset: i91u_reset, \
+ slave_attach: NULL, \
+ bios_param: i91u_biosparam, \
+ can_queue: 1, \
+ this_id: 1, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: 1, \
+ present: 0, \
+ unchecked_isa_dma: 0, \
+ use_clustering: ENABLE_CLUSTERING, \
+ use_new_eh_code: 0 \
+}
+#endif
+#endif
+
+
+#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
+#define ULONG unsigned long
+#define USHORT unsigned short
+#define UCHAR unsigned char
+#define BYTE unsigned char
+#define WORD unsigned short
+#define DWORD unsigned long
+#define UBYTE unsigned char
+#define UWORD unsigned short
+#define UDWORD unsigned long
+#ifdef ALPHA
+#define U32 unsigned int
+#else
+#define U32 unsigned long
+#endif
+
+#ifndef NULL
+#define NULL 0 /* zero */
+#endif
+#ifndef TRUE
+#define TRUE (1) /* boolean true */
+#endif
+#ifndef FALSE
+#define FALSE (0) /* boolean false */
+#endif
+#ifndef FAILURE
+#define FAILURE (-1)
+#endif
+
+#define i91u_MAXQUEUE 2
+#define TOTAL_SG_ENTRY 32
+#define MAX_TARGETS 16
+#define SENSE_SIZE 14
+
+#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */
+#define DMX_VENDOR_ID 0x134a /* Domex's PCI vendor ID */
+#define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */
+#define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */
+#define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */
+#define I920_DEVICE_ID 0x0002 /* Initio's other product ID */
+
+/************************************************************************/
+/* Scatter-Gather Element Structure */
+/************************************************************************/
+typedef struct SG_Struc {
+ U32 SG_Ptr; /* Data Pointer */
+ U32 SG_Len; /* Data Length */
+} SG;
+
+/***********************************************************************
+ SCSI Control Block
+************************************************************************/
+typedef struct Scsi_Ctrl_Blk {
+ U32 SCB_InitioReserved[9]; /* 0 */
+
+ UBYTE SCB_Opcode; /*24 SCB command code */
+ UBYTE SCB_Flags; /*25 SCB Flags */
+ UBYTE SCB_Target; /*26 Target Id */
+ UBYTE SCB_Lun; /*27 Lun */
+ U32 SCB_BufPtr; /*28 Data Buffer Pointer */
+ U32 SCB_BufLen; /*2C Data Allocation Length */
+ UBYTE SCB_SGLen; /*30 SG list # */
+ UBYTE SCB_SenseLen; /*31 Sense Allocation Length */
+ UBYTE SCB_HaStat; /*32 */
+ UBYTE SCB_TaStat; /*33 */
+ UBYTE SCB_CDBLen; /*34 CDB Length */
+ UBYTE SCB_Ident; /*35 Identify */
+ UBYTE SCB_TagMsg; /*36 Tag Message */
+ UBYTE SCB_TagId; /*37 Queue Tag */
+ UBYTE SCB_CDB[12]; /*38 */
+ U32 SCB_SGPAddr; /*44 SG List/Sense Buf phy. Addr. */
+ U32 SCB_SensePtr; /*48 Sense data pointer */
+ void (*SCB_Post) (BYTE *, BYTE *); /*4C POST routine */
+ Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */
+ SG SCB_SGList[TOTAL_SG_ENTRY]; /*54 Start of SG list */
+} SCB;
+
+/* Opcodes of SCB_Opcode */
+#define ExecSCSI 0x1
+#define BusDevRst 0x2
+#define AbortCmd 0x3
+
+/* Bit Definition for SCB_Flags */
+#define SCF_DONE 0x01
+#define SCF_POST 0x02
+#define SCF_SENSE 0x04
+#define SCF_DIR 0x18
+#define SCF_NO_DCHK 0x00
+#define SCF_DIN 0x08
+#define SCF_DOUT 0x10
+#define SCF_NO_XF 0x18
+#define SCF_POLL 0x40
+#define SCF_SG 0x80
+
+/* Error Codes for SCB_HaStat */
+#define HOST_SEL_TOUT 0x11
+#define HOST_DO_DU 0x12
+#define HOST_BUS_FREE 0x13
+#define HOST_BAD_PHAS 0x14
+#define HOST_INV_CMD 0x16
+#define HOST_SCSI_RST 0x1B
+#define HOST_DEV_RST 0x1C
+
+/* Error Codes for SCB_TaStat */
+#define TARGET_CHKCOND 0x02
+#define TARGET_BUSY 0x08
+
+/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
+#define MSG_STAG 0x20
+#define MSG_HTAG 0x21
+#define MSG_OTAG 0x22
+
+/***********************************************************************
+ Target Device Control Structure
+**********************************************************************/
+
+typedef struct Tar_Ctrl_Struc {
+ ULONG TCS_InitioReserved; /* 0 */
+
+ UWORD TCS_DrvFlags; /* 4 */
+ UBYTE TCS_DrvHead; /* 6 */
+ UBYTE TCS_DrvSector; /* 7 */
+} TCS;
+
+/***********************************************************************
+ Target Device Control Structure
+**********************************************************************/
+/* Bit Definition for TCF_DrvFlags */
+#define TCF_DRV_255_63 0x0400
+
+/***********************************************************************
+ Host Adapter Control Structure
+************************************************************************/
+typedef struct Ha_Ctrl_Struc {
+ UWORD HCS_Base; /* 00 */
+ UWORD HCS_BIOS; /* 02 */
+ UBYTE HCS_Intr; /* 04 */
+ UBYTE HCS_SCSI_ID; /* 05 */
+ UBYTE HCS_MaxTar; /* 06 */
+ UBYTE HCS_NumScbs; /* 07 */
+
+ UBYTE HCS_Flags; /* 08 */
+ UBYTE HCS_Index; /* 09 */
+ UBYTE HCS_Reserved[2]; /* 0a */
+ ULONG HCS_InitioReserved[27]; /* 0C */
+ TCS HCS_Tcs[16]; /* 78 -> 16 Targets */
+ Scsi_Cmnd *pSRB_head; /* SRB save queue header */
+ Scsi_Cmnd *pSRB_tail; /* SRB save queue tail */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+ spinlock_t HCS_AvailLock;
+ spinlock_t HCS_SemaphLock;
+ spinlock_t pSRB_lock;
+#endif
+} HCS;
+
+/* Bit Definition for HCB_Flags */
+#define HCF_EXPECT_RESET 0x10
+
+/* SCSI related definition */
+#define DISC_NOT_ALLOW 0x80 /* Disconnect is not allowed */
+#define DISC_ALLOW 0xC0 /* Disconnect is allowed */
diff --git a/drivers/scsi/mac_NCR5380.c b/drivers/scsi/mac_NCR5380.c
index c0a51994a..a562e7f6d 100644
--- a/drivers/scsi/mac_NCR5380.c
+++ b/drivers/scsi/mac_NCR5380.c
@@ -1458,9 +1458,9 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)
- && jiffies < timeout && !hostdata->connected)
+ && time_before(jiffies, timeout) && !hostdata->connected)
;
- if (jiffies >= timeout)
+ if (time_after_eq(jiffies, timeout))
{
printk("scsi : arbitration timeout at %d\n", __LINE__);
NCR5380_write(MODE_REG, MR_BASE);
@@ -1615,7 +1615,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
* only wait for BSY... (Famous german words: Der Klügere gibt nach :-)
*/
- while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) &
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) &
(SR_BSY | SR_IO)));
if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) ==
@@ -1628,7 +1628,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
return -1;
}
#else
- while ((jiffies < timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
+ while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));
#endif
/*
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
new file mode 100644
index 000000000..9e6fa65f4
--- /dev/null
+++ b/drivers/scsi/mac_esp.c
@@ -0,0 +1,691 @@
+/*
+ * 68k mac 53c9[46] scsi driver
+ *
+ * copyright (c) 1998, David Weis weisd3458@uni.edu
+ *
+ * debugging on Quadra 800 and 660AV Michael Schmitz, Dave Kilzer 7/98
+ *
+ * based loosely on cyber_esp.c
+ */
+
+/* these are unused for now */
+#define myreadl(addr) (*(volatile unsigned int *) (addr))
+#define mywritel(b, addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "mac_esp.h"
+
+#include "../../arch/m68k/mac/via6522.h" /* huh? */
+
+#include <asm/io.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/macints.h>
+#include <asm/machw.h>
+
+#include <asm/pgtable.h>
+
+#include <asm/macintosh.h>
+
+extern inline void esp_handle(struct NCR_ESP *esp);
+extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+
+static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count);
+static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP * esp);
+static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length);
+static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length);
+static void dma_ints_off(struct NCR_ESP * esp);
+static void dma_ints_on(struct NCR_ESP * esp);
+static int dma_irq_p(struct NCR_ESP * esp);
+static int dma_irq_p_quick(struct NCR_ESP * esp);
+static void dma_led_off(struct NCR_ESP * esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write);
+static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write);
+
+
+static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev);
+static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev);
+
+static int esp_initialized = 0;
+
+static int setup_num_esps = -1;
+static int setup_disconnect = -1;
+static int setup_nosync = -1;
+static int setup_can_queue = -1;
+static int setup_cmd_per_lun = -1;
+static int setup_sg_tablesize = -1;
+#ifdef SUPPORT_TAGS
+static int setup_use_tagged_queuing = -1;
+#endif
+static int setup_hostid = -1;
+
+/*
+ * Experimental ESP inthandler; check macints.c to make sure dev_id is
+ * set up properly!
+ */
+
+void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+{
+ struct NCR_ESP *esp = (struct NCR_ESP *) dev_id;
+ int irq_p = 0;
+
+ /* Handle the one ESP interrupt showing at this IRQ level. */
+ if(((esp)->irq & 0xff) == irq) {
+ /*
+ * Debug ..
+ */
+ irq_p = esp->dma_irq_p(esp);
+ printk("mac_esp: irq_p %x current %p disconnected %p\n",
+ irq_p, esp->current_SC, esp->disconnected_SC);
+
+ /*
+ * Mac: if we're here, it's an ESP interrupt for sure!
+ */
+ if((esp->current_SC || esp->disconnected_SC)) {
+ esp->dma_ints_off(esp);
+
+ ESPIRQ(("I%d(", esp->esp_id));
+ esp_handle(esp);
+ ESPIRQ((")"));
+
+ esp->dma_ints_on(esp);
+ }
+ }
+}
+
+/*
+ * Debug hooks; use for playing with the interrupt flag testing and interrupt
+ * acknowledge on the various machines
+ */
+
+void scsi_esp_polled(int irq, void *dev_id, struct pt_regs *pregs)
+{
+ if (esp_initialized == 0)
+ return;
+
+ mac_esp_intr(irq, dev_id, pregs);
+}
+
+void fake_intr(int irq, void *dev_id, struct pt_regs *pregs)
+{
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: got irq\n");
+#endif
+
+ mac_esp_intr(irq, dev_id, pregs);
+}
+
+void fake_drq(int irq, void *dev_id, struct pt_regs *pregs)
+{
+ printk("mac_esp: got drq\n");
+}
+
+#define DRIVER_SETUP
+
+/*
+ * Function : mac_scsi_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ * equal to the number of ints.
+ *
+ * Currently unused in the new driver; need to add settable parameters to the
+ * detect function.
+ *
+ */
+
+void mac_esp_setup(char *str, int *ints) {
+#ifdef DRIVER_SETUP
+ /* Format of mac53c9x parameter is:
+ * mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
+ * Negative values mean don't change.
+ */
+
+ /* Grmbl... the standard parameter parsing can't handle negative numbers
+ * :-( So let's do it ourselves!
+ */
+
+ int i = ints[0]+1, fact;
+
+ while( str && (isdigit(*str) || *str == '-') && i <= 10) {
+ if (*str == '-')
+ fact = -1, ++str;
+ else
+ fact = 1;
+ ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
+ if ((str = strchr( str, ',' )) != NULL)
+ ++str;
+ }
+ ints[0] = i-1;
+
+ if (ints[0] < 1) {
+ printk( "mac_esp_setup: no arguments!\n" );
+ return;
+ }
+
+ if (ints[0] >= 1) {
+ if (ints[1] > 0)
+ /* no limits on this, just > 0 */
+ if (ints[1] >= 0 && ints[1] <= 2)
+ setup_num_esps = ints[1];
+ else if (ints[1] > 2)
+ printk( "mac_esp_setup: invalid number of hosts %d !\n", ints[1] );
+ }
+ if (ints[0] >= 2) {
+ if (ints[2] > 0)
+ setup_disconnect = ints[2];
+ }
+ if (ints[0] >= 3) {
+ if (ints[3] >= 0) {
+ setup_nosync = ints[3];
+ }
+ }
+ if (ints[0] >= 4) {
+ if (ints[4] > 0)
+ /* no limits on this, just > 0 */
+ setup_can_queue = ints[4];
+ }
+ if (ints[0] >= 5) {
+ if (ints[5] > 0)
+ setup_cmd_per_lun = ints[5];
+ }
+ if (ints[0] >= 6) {
+ if (ints[6] >= 0) {
+ setup_sg_tablesize = ints[6];
+ /* Must be <= SG_ALL (255) */
+ if (setup_sg_tablesize > SG_ALL)
+ setup_sg_tablesize = SG_ALL;
+ }
+ }
+ if (ints[0] >= 7) {
+ /* Must be between 0 and 7 */
+ if (ints[7] >= 0 && ints[7] <= 7)
+ setup_hostid = ints[7];
+ else if (ints[7] > 7)
+ printk( "mac_esp_setup: invalid host ID %d !\n", ints[7] );
+ }
+#ifdef SUPPORT_TAGS
+ if (ints[0] >= 8) {
+ if (ints[8] >= 0)
+ setup_use_tagged_queuing = !!ints[8];
+ }
+#endif
+#endif
+}
+
+/*
+ * ESP address 'detection'
+ */
+
+unsigned long get_base(int chip_num)
+{
+ /*
+ * using the chip_num and mac model, figure out where the
+ * chips are mapped
+ */
+
+ unsigned long io_base = 0x50f00000;
+ unsigned int second_offset = 0x402;
+ unsigned long scsi_loc = 0;
+
+ switch (macintosh_config->scsi_type) {
+
+ /* 950, 900, 700 */
+ case MAC_SCSI_QUADRA2:
+ scsi_loc = io_base + 0xf000 + ((chip_num == 0) ? 0 : second_offset);
+ break;
+
+ /* av's */
+ case MAC_SCSI_QUADRA3:
+ scsi_loc = io_base + 0x18000 + ((chip_num == 0) ? 0 : second_offset);
+ break;
+
+ /* most quadra/centris models are like this */
+ case MAC_SCSI_QUADRA:
+ scsi_loc = io_base + 0x10000;
+ break;
+
+ default:
+ printk("mac_esp: get_base: hit default!\n");
+ scsi_loc = io_base + 0x10000;
+ break;
+
+ } /* switch */
+
+ printk("mac_esp: io base at 0x%lx\n", scsi_loc);
+
+ return scsi_loc;
+}
+
+/*
+ * Model dependent ESP setup
+ */
+
+int mac_esp_detect(Scsi_Host_Template * tpnt)
+{
+ int quick = 0;
+ int chipnum, chipspresent = 0;
+#if 0
+ unsigned long timeout;
+#endif
+
+ /* what do we have in this machine... */
+ if (MACHW_PRESENT(MAC_SCSI_96)) {
+ chipspresent ++;
+ }
+
+ if (MACHW_PRESENT(MAC_SCSI_96_2)) {
+ chipspresent ++;
+ }
+
+ /* number of ESPs present ? */
+ if (setup_num_esps >= 0) {
+ if (chipspresent >= setup_num_esps)
+ chipspresent = setup_num_esps;
+ else
+ printk("mac_esp_detect: num_hosts detected %d setup %d \n",
+ chipspresent, setup_num_esps);
+ }
+
+ /* TODO: add disconnect / nosync flags */
+
+ /* setup variables */
+ tpnt->can_queue =
+ (setup_can_queue > 0) ? setup_can_queue : 7;
+ tpnt->cmd_per_lun =
+ (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1;
+ tpnt->sg_tablesize =
+ (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL;
+
+ if (setup_hostid >= 0)
+ tpnt->this_id = setup_hostid;
+ else {
+ /* use 7 as default */
+ tpnt->this_id = 7;
+ }
+
+#ifdef SUPPORT_TAGS
+ if (setup_use_tagged_queuing < 0)
+ setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
+#endif
+
+ for (chipnum = 0; chipnum < chipspresent; chipnum ++) {
+ struct NCR_ESP * esp;
+
+ esp = esp_allocate(tpnt, (void *) NULL);
+ esp->eregs = (struct ESP_regs *) get_base(chipnum);
+
+ esp->dma_irq_p = &esp_dafb_dma_irq_p;
+ if (chipnum == 0) {
+
+ if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
+ /* most machines except those below :-) */
+ quick = 1;
+ esp->dma_irq_p = &esp_iosb_dma_irq_p;
+ } else if (macintosh_config->scsi_type == MAC_SCSI_QUADRA3) {
+ /* mostly av's */
+ quick = 0;
+ } else {
+ /* q950, 900, 700 */
+ quick = 1;
+ writel(0x1d1, 0xf9800024);
+ esp->dregs = (void *) 0xf9800024;
+ }
+
+ } else { /* chipnum */
+
+ quick = 1;
+ writel(0x1d1, 0xf9800028);
+ esp->dregs = (void *) 0xf9800028;
+
+ } /* chipnum == 0 */
+
+
+ /* use pio for command bytes; pio for message/data: TBI */
+ esp->do_pio_cmds = 1;
+
+ /* various functions */
+ esp->dma_bytes_sent = &dma_bytes_sent;
+ esp->dma_can_transfer = &dma_can_transfer;
+ esp->dma_dump_state = &dma_dump_state;
+ esp->dma_init_read = NULL;
+ esp->dma_init_write = NULL;
+ esp->dma_ints_off = &dma_ints_off;
+ esp->dma_ints_on = &dma_ints_on;
+
+ esp->dma_ports_p = &dma_ports_p;
+
+
+ /* Optional functions */
+ esp->dma_barrier = NULL;
+ esp->dma_drain = NULL;
+ esp->dma_invalidate = NULL;
+ esp->dma_irq_entry = NULL;
+ esp->dma_irq_exit = NULL;
+ esp->dma_led_on = NULL;
+ esp->dma_led_off = NULL;
+ esp->dma_poll = NULL;
+ esp->dma_reset = NULL;
+
+ /* SCSI chip speed */
+ /* below esp->cfreq = 40000000; */
+
+
+ if (quick) {
+ /* 'quick' means there's handshake glue logic like in the 5380 case */
+ esp->dma_setup = &dma_setup_quick;
+ } else {
+ esp->dma_setup = &dma_setup;
+ }
+
+ if (chipnum == 0) {
+
+ esp->irq = IRQ_MAC_SCSI;
+
+ request_irq(IRQ_MAC_SCSI, esp_intr, 0, "Mac ESP SCSI", esp);
+ request_irq(IRQ_MAC_SCSIDRQ, fake_drq, 0, "Mac ESP DRQ", esp);
+
+ if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
+ esp->cfreq = 16500000;
+ } else {
+ esp->cfreq = 25000000;
+ }
+
+
+ } else { /* chipnum == 1 */
+
+ esp->irq = IRQ_MAC_SCSIDRQ;
+
+ request_irq(IRQ_MAC_SCSIDRQ, esp_intr, 0, "Mac ESP SCSI 2", esp);
+
+ esp->cfreq = 25000000;
+
+ }
+
+ if (quick) {
+ printk("esp: using quick version\n");
+ }
+
+ printk("esp: addr at 0x%p\n", esp->eregs);
+
+ esp->scsi_id = 7;
+ esp->diff = 0;
+
+ esp_initialize(esp);
+
+ } /* for chipnum */
+
+ if (chipspresent)
+ printk("\nmac_esp: %d esp controllers found\n", chipspresent);
+
+ esp_initialized = chipspresent;
+
+ return chipspresent;
+}
+
+/*
+ * I've been wondering what this is supposed to do, for some time. Talking
+ * to Allen Briggs: These machines have an extra register someplace where the
+ * DRQ pin of the ESP can be monitored. That isn't useful for determining
+ * anything else (such as reselect interrupt or other magic) though.
+ * Maybe make the semantics should be changed like
+ * if (esp->current_SC)
+ * ... check DRQ flag ...
+ * else
+ * ... disconnected, check pending VIA interrupt ...
+ *
+ * There's a problem with using the dabf flag or mac_irq_pending() here: both
+ * seem to return 1 even though no interrupt is currently pending, resulting
+ * in esp_exec_cmd() holding off the next command, and possibly infinite loops
+ * in esp_intr().
+ * Short term fix: just use esp_status & ESP_STAT_INTR here, as long as we
+ * use simple PIO. The DRQ status will be important when implementing pseudo
+ * DMA mode (set up ESP transfer count, return, do a batch of bytes in PIO or
+ * 'hardware handshake' mode upon DRQ).
+ * If you plan on changing this (i.e. to save the esp_status register access in
+ * favor of a VIA register access or a shadow register for the IFR), make sure
+ * to try a debug version of this first to monitor what registers would be a good
+ * indicator of the ESP interrupt.
+ */
+
+static int esp_dafb_dma_irq_p(struct NCR_ESP * esp)
+{
+ unsigned int ret;
+ int sreg = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n",
+ readl(esp->dregs), mac_irq_pending(IRQ_MAC_SCSI));
+#endif
+
+ sreg &= ESP_STAT_INTR;
+
+ /*
+ * maybe working; this is essentially what's used for iosb_dma_irq_p
+ */
+ if (sreg)
+ return 1;
+ else
+ return 0;
+
+ /*
+ * didn't work ...
+ */
+#if 0
+ if (esp->current_SC)
+ ret = readl(esp->dregs) & 0x200;
+ else if (esp->disconnected_SC)
+ ret = 1; /* sreg ?? */
+ else
+ ret = mac_irq_pending(IRQ_MAC_SCSI);
+
+ return(ret);
+#endif
+
+}
+
+/*
+ * See above: testing mac_irq_pending always returned 8 (SCSI IRQ) regardless
+ * of the actual ESP status.
+ */
+
+static int esp_iosb_dma_irq_p(struct NCR_ESP * esp)
+{
+ int ret = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
+ int sreg = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n",
+ mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI),
+ sreg, esp->current_SC, esp->disconnected_SC);
+#endif
+
+ sreg &= ESP_STAT_INTR;
+
+ if (sreg)
+ return (sreg);
+ else
+ return 0;
+}
+
+/*
+ * This seems to be OK for PIO at least ... usually 0 after PIO.
+ */
+
+static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count)
+{
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma bytes sent = %x\n", fifo_count);
+#endif
+
+ return fifo_count;
+}
+
+/*
+ * dma_can_transfer is used to switch between DMA and PIO, if DMA (pseudo)
+ * is ever implemented. Returning 0 here will use PIO.
+ */
+
+static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd * sp)
+{
+ unsigned long sz = sp->SCp.this_residual;
+#if 0 /* no DMA yet; make conditional */
+ if (sz > 0x10000000) {
+ sz = 0x10000000;
+ }
+ printk("mac_esp: dma can transfer = 0lx%x\n", sz);
+#else
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: pio to transfer = %ld\n", sz);
+#endif
+
+ sz = 0;
+#endif
+ return sz;
+}
+
+/*
+ * Not yet ...
+ */
+
+static void dma_dump_state(struct NCR_ESP * esp)
+{
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_dump_state: called\n");
+#endif
+#if 0
+ ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
+ esp->esp_id, ((struct mac_dma_registers *)
+ (esp->dregs))->cond_reg));
+#endif
+}
+
+/*
+ * DMA setup: should be used to set up the ESP transfer count for pseudo
+ * DMA transfers; need a DRQ transfer function to do the actual transfer
+ */
+
+static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length)
+{
+ printk("mac_esp: dma_init_read\n");
+}
+
+
+static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length)
+{
+ printk("mac_esp: dma_init_write\n");
+}
+
+
+static void dma_ints_off(struct NCR_ESP * esp)
+{
+ mac_turnoff_irq(esp->irq);
+}
+
+
+static void dma_ints_on(struct NCR_ESP * esp)
+{
+ mac_turnon_irq(esp->irq);
+}
+
+/*
+ * generic dma_irq_p(), unused
+ */
+
+static int dma_irq_p(struct NCR_ESP * esp)
+{
+ int i = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_irq_p status %d\n", i);
+#endif
+
+ return (i & ESP_STAT_INTR);
+}
+
+static int dma_irq_p_quick(struct NCR_ESP * esp)
+{
+ /*
+ * Copied from iosb_dma_irq_p()
+ */
+ int ret = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
+ int sreg = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n",
+ mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI),
+ sreg, esp->current_SC, esp->disconnected_SC);
+#endif
+
+ sreg &= ESP_STAT_INTR;
+
+ if (sreg)
+ return (sreg);
+ else
+ return 0;
+
+}
+
+static void dma_led_off(struct NCR_ESP * esp)
+{
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_led_off: called\n");
+#endif
+}
+
+
+static void dma_led_on(struct NCR_ESP * esp)
+{
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_led_on: called\n");
+#endif
+}
+
+
+static int dma_ports_p(struct NCR_ESP * esp)
+{
+ return 0;
+}
+
+
+static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write)
+{
+
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_setup\n");
+#endif
+
+ if (write) {
+ dma_init_read(esp, (char *) addr, count);
+ } else {
+ dma_init_write(esp, (char *) addr, count);
+ }
+}
+
+
+static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write)
+{
+#ifdef DEBUG_MAC_ESP
+ printk("mac_esp: dma_setup_quick\n");
+#endif
+}
diff --git a/drivers/scsi/mac_esp.h b/drivers/scsi/mac_esp.h
new file mode 100644
index 000000000..9de3186d0
--- /dev/null
+++ b/drivers/scsi/mac_esp.h
@@ -0,0 +1,41 @@
+
+/*
+mac_esp.h
+
+copyright 1997 David Weis, weisd3458@uni.edu
+*/
+
+
+#include "NCR53C9x.h"
+
+#ifndef MAC_ESP_H
+#define MAC_ESP_H
+
+/* #define DEBUG_MAC_ESP */
+
+extern int mac_esp_detect(struct SHT *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+
+
+#define SCSI_MAC_ESP { proc_dir: &proc_scsi_esp, \
+ name: "Mac 53C9x SCSI", \
+ detect: mac_esp_detect, \
+ release: NULL, \
+ info: esp_info, \
+ /* command: esp_command, */ \
+ queuecommand: esp_queue, \
+ abort: esp_abort, \
+ reset: esp_reset, \
+ can_queue: 7, \
+ this_id: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: 1, \
+ use_clustering: DISABLE_CLUSTERING, \
+ use_new_eh_code: 0 }
+
+#endif /* MAC_ESP_H */
+
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 08beec417..466fcb91d 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -662,7 +662,7 @@ static void mac_scsi_reset_boot( void )
NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
NCR5380_read( RESET_PARITY_INTERRUPT_REG );
- for( end = jiffies + AFTER_RESET_DELAY; jiffies < end; )
+ for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
barrier();
/* switch on SCSI IRQ again */
diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
new file mode 100644
index 000000000..9755f8ee7
--- /dev/null
+++ b/drivers/scsi/mca_53c9x.c
@@ -0,0 +1,476 @@
+/* mca_53c9x.c: Driver for the SCSI adapter found on NCR 35xx
+ * (and maybe some other) Microchannel machines
+ *
+ * Code taken mostly from Cyberstorm SCSI drivers
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
+ *
+ * The CyberStorm SCSI driver (and this driver) is based on David S. Miller's
+ * ESP driver * for the Sparc computers.
+ *
+ * Special thanks to Ken Stewart at Symbios (LSI) for helping with info on
+ * the 86C01. I was on the brink of going ga-ga...
+ *
+ * Also thanks to Jesper Skov for helping me with info on how the Amiga
+ * does things...
+ */
+
+/*
+ * This is currently only set up to use one 53c9x card at a time; it could be
+ * changed fairly easily to detect/use more than one, but I'm not too sure how
+ * many cards that use the 53c9x on MCA systems there are (if, in fact, there
+ * are cards that use them, other than the one built into some NCR systems)...
+ * If anyone requests this, I'll throw it in, otherwise it's not worth the
+ * effort.
+ */
+
+/*
+ * Info on the 86C01 MCA interface chip at the bottom, if you care enough to
+ * look.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "mca_53c9x.h"
+
+#include <asm/dma.h>
+#include <linux/mca.h>
+#include <asm/irq.h>
+#include <asm/mca_dma.h>
+
+#include <asm/pgtable.h>
+
+static int dma_bytes_sent(struct NCR_ESP *, int);
+static int dma_can_transfer(struct NCR_ESP *, Scsi_Cmnd *);
+static void dma_dump_state(struct NCR_ESP *);
+static void dma_init_read(struct NCR_ESP *, __u32, int);
+static void dma_init_write(struct NCR_ESP *, __u32, int);
+static void dma_ints_off(struct NCR_ESP *);
+static void dma_ints_on(struct NCR_ESP *);
+static int dma_irq_p(struct NCR_ESP *);
+static int dma_ports_p(struct NCR_ESP *);
+static void dma_setup(struct NCR_ESP *, __u32, int, int);
+static void dma_led_on(struct NCR_ESP *);
+static void dma_led_off(struct NCR_ESP *);
+
+/* This is where all commands are put before they are trasfered to the
+ * 53c9x via PIO.
+ */
+
+volatile unsigned char cmd_buffer[16];
+
+/*
+ * We keep the structure that is used to access the registers on the 53c9x
+ * here.
+ */
+
+static struct ESP_regs eregs;
+
+/***************************************************************** Detection */
+int mca_esp_detect(Scsi_Host_Template *tpnt)
+{
+ struct NCR_ESP *esp;
+ static int io_port_by_pos[] = MCA_53C9X_IO_PORTS;
+ int mca_53c9x_ids[] = MCA_53C9X_IDS;
+ int *id_to_check = mca_53c9x_ids;
+ int slot;
+ int pos[3];
+ unsigned int tmp_io_addr;
+ unsigned char tmp_byte;
+
+
+ if (!MCA_bus)
+ return 0;
+
+ while (*id_to_check) {
+ if ((slot = mca_find_adapter(*id_to_check, 0)) !=
+ MCA_NOTFOUND)
+ {
+ esp = esp_allocate(tpnt, (void *) NULL);
+
+ pos[0] = mca_read_stored_pos(slot, 2);
+ pos[1] = mca_read_stored_pos(slot, 3);
+ pos[2] = mca_read_stored_pos(slot, 4);
+
+ esp->eregs = &eregs;
+
+ /*
+ * IO port base is given in the first (non-ID) pos
+ * register, like so:
+ *
+ * Bits 3 2 1 IO base
+ * ----------------------------
+ * 0 0 0 <disabled>
+ * 0 0 1 0x0240
+ * 0 1 0 0x0340
+ * 0 1 1 0x0400
+ * 1 0 0 0x0420
+ * 1 0 1 0x3240
+ * 1 1 0 0x8240
+ * 1 1 1 0xA240
+ */
+
+ tmp_io_addr =
+ io_port_by_pos[(pos[0] & 0x0E) >> 1];
+
+ esp->eregs->io_addr = tmp_io_addr + 0x10;
+
+ if (esp->eregs->io_addr == 0x0000) {
+ printk("Adapter is disabled.\n");
+ break;
+ }
+
+ /*
+ * IRQ is specified in bits 4 and 5:
+ *
+ * Bits 4 5 IRQ
+ * -----------------------
+ * 0 0 3
+ * 0 1 5
+ * 1 0 7
+ * 1 1 9
+ */
+
+ esp->irq = ((pos[0] & 0x30) >> 3) + 3;
+
+ /*
+ * DMA channel is in the low 3 bits of the second
+ * POS register
+ */
+
+ esp->dma = pos[1] & 7;
+ esp->slot = slot;
+
+ if (request_irq(esp->irq, esp_intr, 0,
+ "NCR 53c9x SCSI", esp_intr))
+ {
+ printk("Unable to request IRQ %d.\n", esp->irq);
+ return 0;
+ }
+
+ if (request_dma(esp->dma, "NCR 53c9x SCSI")) {
+ printk("Unable to request DMA channel %d.\n",
+ esp->dma);
+ free_irq(esp->irq, esp_intr);
+ return 0;
+ }
+
+ request_region(tmp_io_addr, 32, "NCR 53c9x SCSI");
+
+ /*
+ * 86C01 handles DMA, IO mode, from address
+ * (base + 0x0a)
+ */
+
+ mca_disable_dma(esp->dma);
+ mca_set_dma_io(esp->dma, tmp_io_addr + 0x0a);
+ mca_enable_dma(esp->dma);
+
+ /* Tell the 86C01 to give us interrupts */
+
+ tmp_byte = inb(tmp_io_addr + 0x02) | 0x40;
+ outb(tmp_byte, tmp_io_addr + 0x02);
+
+ /*
+ * Scsi ID -- general purpose register, hi
+ * 2 bits; add 4 to this number to get the
+ * ID
+ */
+
+ esp->scsi_id = ((pos[2] & 0xC0) >> 6) + 4;
+
+ /* Do command transfer with programmed I/O */
+
+ esp->do_pio_cmds = 1;
+
+ /* Required functions */
+
+ esp->dma_bytes_sent = &dma_bytes_sent;
+ esp->dma_can_transfer = &dma_can_transfer;
+ esp->dma_dump_state = &dma_dump_state;
+ esp->dma_init_read = &dma_init_read;
+ esp->dma_init_write = &dma_init_write;
+ esp->dma_ints_off = &dma_ints_off;
+ esp->dma_ints_on = &dma_ints_on;
+ esp->dma_irq_p = &dma_irq_p;
+ esp->dma_ports_p = &dma_ports_p;
+ esp->dma_setup = &dma_setup;
+
+ /* Optional functions */
+
+ esp->dma_barrier = 0;
+ esp->dma_drain = 0;
+ esp->dma_invalidate = 0;
+ esp->dma_irq_entry = 0;
+ esp->dma_irq_exit = 0;
+ esp->dma_led_on = dma_led_on;
+ esp->dma_led_off = dma_led_off;
+ esp->dma_poll = 0;
+ esp->dma_reset = 0;
+
+ /* Set the command buffer */
+
+ esp->esp_command = (volatile unsigned char*)
+ cmd_buffer;
+ esp->esp_command_dvma = virt_to_bus(cmd_buffer);
+
+ /* SCSI chip speed */
+
+ esp->cfreq = 25000000;
+
+ /* Differential SCSI? I think not. */
+
+ esp->diff = 0;
+
+ esp_initialize(esp);
+
+ printk(" Adapter found in slot %2d: io port 0x%x "
+ "irq %d dma channel %d\n", slot + 1, tmp_io_addr,
+ esp->irq, esp->dma);
+
+ mca_set_adapter_name(slot, "NCR 53C9X SCSI Adapter");
+ mca_mark_as_used(slot);
+
+ break;
+ }
+
+ id_to_check++;
+ }
+
+ return esps_in_use;
+}
+
+
+/******************************************************************* Release */
+
+int mca_esp_release(struct Scsi_Host *host)
+{
+ struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata;
+ unsigned char tmp_byte;
+
+
+ /*
+ * Tell the 86C01 to stop sending interrupts
+ */
+
+ tmp_byte = inb(esp->eregs->io_addr - 0x0E);
+ tmp_byte &= ~0x40;
+ outb(tmp_byte, esp->eregs->io_addr - 0x0E);
+
+ free_irq(esp->irq, esp_intr);
+ free_dma(esp->dma);
+
+ mca_mark_as_unused(esp->eregs->slot);
+
+ return 0;
+}
+
+/************************************************************* DMA Functions */
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+ /* Ask the 53c9x. It knows. */
+
+ return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+ /*
+ * The MCA dma channels can only do up to 128K bytes at a time.
+ * (16 bit mode)
+ */
+
+ unsigned long sz = sp->SCp.this_residual;
+ if(sz > 0x20000)
+ sz = 0x20000;
+ return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+ /*
+ * Doesn't quite match up to the other drivers, but we do what we
+ * can.
+ */
+
+ ESPLOG(("esp%d: dma channel <%d>\n", esp->esp_id, esp->dma));
+ ESPLOG(("bytes left to dma: %d\n", mca_get_dma_residue(esp->dma)));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+ unsigned long flags;
+
+
+ save_flags(flags);
+ cli();
+
+ mca_disable_dma(esp->dma);
+ mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_16 |
+ MCA_DMA_MODE_IO);
+ mca_set_dma_addr(esp->dma, addr);
+ mca_set_dma_count(esp->dma, length / 2); /* !!! */
+ mca_enable_dma(esp->dma);
+
+ restore_flags(flags);
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+ unsigned long flags;
+
+
+ save_flags(flags);
+ cli();
+
+ mca_disable_dma(esp->dma);
+ mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_WRITE |
+ MCA_DMA_MODE_16 | MCA_DMA_MODE_IO);
+ mca_set_dma_addr(esp->dma, addr);
+ mca_set_dma_count(esp->dma, length / 2); /* !!! */
+ mca_enable_dma(esp->dma);
+
+ restore_flags(flags);
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+ /*
+ * Tell the 'C01 to shut up. All interrupts are routed through it.
+ */
+
+ outb(inb(esp->eregs->io_addr - 0x0E) & ~0x40,
+ esp->eregs->io_addr - 0x0E);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+ /*
+ * Ok. You can speak again.
+ */
+
+ outb(inb(esp->eregs->io_addr - 0x0E) | 0x40,
+ esp->eregs->io_addr - 0x0E);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+ /*
+ * DaveM says that this should return a "yes" if there is an interrupt
+ * or a DMA error occurred. I copied the Amiga driver's semantics,
+ * though, because it seems to work and we can't really tell if
+ * a DMA error happened. This gives the "yes" if the scsi chip
+ * is sending an interrupt and no DMA activity is taking place
+ */
+
+ return (!(inb(esp->eregs->io_addr - 0x04) & 1) &&
+ !(inb(esp->eregs->io_addr - 0x04) & 2) );
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+ /*
+ * Check to see if interrupts are enabled on the 'C01 (in case abort
+ * is entered multiple times, so we only do the abort once)
+ */
+
+ return (inb(esp->eregs->io_addr - 0x0E) & 0x40) ? 1:0;
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+ if(write){
+ dma_init_write(esp, addr, count);
+ } else {
+ dma_init_read(esp, addr, count);
+ }
+}
+
+/*
+ * These will not play nicely with other disk controllers that try to use the
+ * disk active LED... but what can you do? Don't answer that.
+ *
+ * Stolen shamelessly from ibmmca.c -- IBM Microchannel SCSI adapter driver
+ *
+ */
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+ outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR);
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+ outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR);
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = MCA_53C9X;
+#include "scsi_module.c"
+#endif
+
+/*
+ * OK, here's the goods I promised. The NCR 86C01 is an MCA interface chip
+ * that handles enabling/diabling IRQ, dma interfacing, IO port selection
+ * and other fun stuff. It takes up 16 addresses, and the chip it is
+ * connnected to gets the following 16. Registers are as follows:
+ *
+ * Offsets 0-1 : Card ID
+ *
+ * Offset 2 : Mode enable register --
+ * Bit 7 : Data Word width (1 = 16, 0 = 8)
+ * Bit 6 : IRQ enable (1 = enabled)
+ * Bits 5,4 : IRQ select
+ * 0 0 : IRQ 3
+ * 0 1 : IRQ 5
+ * 1 0 : IRQ 7
+ * 1 1 : IRQ 9
+ * Bits 3-1 : Base Address
+ * 0 0 0 : <disabled>
+ * 0 0 1 : 0x0240
+ * 0 1 0 : 0x0340
+ * 0 1 1 : 0x0400
+ * 1 0 0 : 0x0420
+ * 1 0 1 : 0x3240
+ * 1 1 0 : 0x8240
+ * 1 1 1 : 0xA240
+ * Bit 0 : Card enable (1 = enabled)
+ *
+ * Offset 3 : DMA control register --
+ * Bit 7 : DMA enable (1 = enabled)
+ * Bits 6,5 : Preemt Count Select (transfers to complete after
+ * 'C01 has been preempted on MCA bus)
+ * 0 0 : 0
+ * 0 1 : 1
+ * 1 0 : 3
+ * 1 1 : 7
+ * (all these wacky numbers; I'm sure there's a reason somewhere)
+ * Bit 4 : Fairness enable (1 = fair bus priority)
+ * Bits 3-0 : Arbitration level (0-15 consecutive)
+ *
+ * Offset 4 : General purpose register
+ * Bits 7-3 : User definable (here, 7,6 are SCSI ID)
+ * Bits 2-0 : reserved
+ *
+ * Offset 10 : DMA decode register (used for IO based DMA; also can do
+ * PIO through this port)
+ *
+ * Offset 12 : Status
+ * Bits 7-2 : reserved
+ * Bit 1 : DMA pending (1 = pending)
+ * Bit 0 : IRQ pending (0 = pending)
+ *
+ * Exciting, huh?
+ *
+ */
diff --git a/drivers/scsi/mca_53c9x.h b/drivers/scsi/mca_53c9x.h
new file mode 100644
index 000000000..57d1d3ff9
--- /dev/null
+++ b/drivers/scsi/mca_53c9x.h
@@ -0,0 +1,66 @@
+/* mca_53c94.h: Defines and structures for the SCSI adapter found on NCR 35xx
+ * (and maybe some other) Microchannel machines.
+ *
+ * Code taken mostly from Cyberstorm SCSI drivers
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
+ * 1998
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef MCA_53C9X_H
+#define MCA_53C9X_H
+
+/*
+ * From ibmmca.c (IBM scsi controller card driver) -- used for turning PS2 disk
+ * activity LED on and off
+ */
+
+#define PS2_SYS_CTR 0x92
+
+extern int mca_esp_detect(struct SHT *);
+extern int mca_esp_release(struct Scsi_Host *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+ int hostno, int inout);
+
+
+#define MCA_53C9X { proc_dir: &proc_scsi_esp, \
+ name: "NCR 53c9x SCSI", \
+ detect: mca_esp_detect, \
+ release: mca_esp_release, \
+ queuecommand: esp_queue, \
+ abort: esp_abort, \
+ reset: esp_reset, \
+ can_queue: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: 1, \
+ unchecked_isa_dma: 1, \
+ use_clustering: DISABLE_CLUSTERING }
+
+/* Ports the ncr's 53c94 can be put at; indexed by pos register value */
+
+#define MCA_53C9X_IO_PORTS { \
+ 0x0000, 0x0240, 0x0340, 0x0400, \
+ 0x0420, 0x3240, 0x8240, 0xA240, \
+ }
+
+/*
+ * Supposedly there were some cards put together with the 'c9x and 86c01. If
+ * they have different ID's from the ones on the 3500 series machines,
+ * you can add them here and hopefully things will work out.
+ */
+
+#define MCA_53C9X_IDS { \
+ 0x7F4C, \
+ 0x0000, \
+ }
+
+#endif /* MCA_53C9X_H */
+
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
new file mode 100644
index 000000000..13882a253
--- /dev/null
+++ b/drivers/scsi/megaraid.c
@@ -0,0 +1,1353 @@
+/*===================================================================
+ *
+ * Linux MegaRAID device driver
+ *
+ * Copyright 1998 American Megatrends 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.
+ *
+ * Version : 0.92
+ *
+ * Description: Linux device driver for AMI MegaRAID controller
+ *
+ * History:
+ *
+ * Version 0.90:
+ * Works and has been tested with the MegaRAID 428 controller, and
+ * the MegaRAID 438 controller. Probably works with the 466 also,
+ * but not tested.
+ *
+ * Version 0.91:
+ * Aligned mailbox area on 16-byte boundry.
+ * Added schedule() at the end to properly clean up.
+ * Made improvements for conformity to linux driver standards.
+ *
+ * Version 0.92:
+ * Added support for 2.1 kernels.
+ * Reads from pci_dev struct, so it's not dependent on pcibios.
+ * Added some missing virt_to_bus() translations.
+ * Added support for SMP.
+ * Changed global cli()'s to spinlocks for 2.1, and simulated
+ * spinlocks for 2.0.
+ * Removed setting of SA_INTERRUPT flag when requesting Irq.
+ *
+ * Version 0.92ac:
+ * Small changes to the comments/formatting. Plus a couple of
+ * added notes. Returned to the authors. No actual code changes
+ * save printk levels.
+ * 8 Oct 98 Alan Cox <alan.cox@linux.org>
+ *
+ * Merged with 2.1.131 source tree.
+ * 12 Dec 98 K. Baranowski <kgb@knm.org.pl>
+ *
+ * BUGS:
+ * Tested with 2.1.90, but unfortunately there is a bug in pci.c which
+ * fails to detect our controller. Does work with 2.1.118--don't know
+ * which kernel in between it was fixed in.
+ * With SMP enabled under 2.1.118 with more than one processor, gets an
+ * error message "scsi_end_request: buffer-list destroyed" under heavy
+ * IO, but doesn't seem to affect operation, or data integrity. The
+ * message doesn't occur without SMP enabled, or with one proccessor with
+ * SMP enabled, or under any combination under 2.0 kernels.
+ *
+ *===================================================================*/
+#define QISR 1
+
+#define CRLFSTR "\n"
+
+#define MULTIQ 1
+
+#include <linux/version.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+
+#if LINUX_VERSION_CODE >= 0x20100
+char kernel_version[] = UTS_RELEASE;
+
+/* originally ported by Dell Corporation; updated, released, and maintained by
+ American Megatrends */
+MODULE_AUTHOR("American Megatrends Inc.");
+MODULE_DESCRIPTION("AMI MegaRAID driver");
+#endif
+#endif
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/blk.h>
+#include <linux/wait.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/malloc.h> /* for kmalloc() */
+#if LINUX_VERSION_CODE < 0x20100
+#include <linux/bios32.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+
+#include "megaraid.h"
+
+/*================================================================
+ *
+ * #Defines
+ *
+ *================================================================*/
+
+#if LINUX_VERSION_CODE < 0x020100
+#define ioremap vremap
+#define iounmap vfree
+
+/* simulate spin locks */
+typedef struct {volatile char lock;} spinlock_t;
+#define spin_lock_init(x) { (x)->lock = 0;}
+#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\
+ (x)->lock=1; save_flags(flags);\
+ cli();}
+#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);}
+
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020100
+#define queue_task_irq(a,b) queue_task(a,b)
+#define queue_task_irq_off(a,b) queue_task(a,b)
+#endif
+
+#define MAX_SERBUF 160
+#define COM_BASE 0x2f8
+
+#define ENQUEUE(obj,type,list,next) \
+{ type **node; long cpuflag; \
+ spin_lock_irqsave(&mega_lock,cpuflag);\
+ for(node=&(list); *node; node=(type **)&(*node)->##next); \
+ (*node) = obj; \
+ (*node)->##next = NULL; \
+ spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
+
+#define DEQUEUE(obj,type,list,next) \
+{ long cpuflag; \
+ spin_lock_irqsave(&mega_lock,cpuflag);\
+ if ((obj=list) != NULL) {\
+ list = (type *)(list)->##next; \
+ } \
+ spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
+
+u_long RDINDOOR(mega_host_config *megaCfg)
+{
+ return readl(megaCfg->base + 0x20);
+}
+
+void WRINDOOR(mega_host_config *megaCfg, u_long value)
+{
+ writel(value,megaCfg->base+0x20);
+}
+
+u_long RDOUTDOOR(mega_host_config *megaCfg)
+{
+ return readl(megaCfg->base+0x2C);
+}
+
+void WROUTDOOR(mega_host_config *megaCfg, u_long value)
+{
+ writel(value,megaCfg->base+0x2C);
+}
+
+/*================================================================
+ *
+ * Function prototypes
+ *
+ *================================================================*/
+static int MegaIssueCmd(mega_host_config *megaCfg,
+ u_char *mboxData,
+ mega_scb *scb,
+ int intr);
+static int build_sglist(mega_host_config *megaCfg, mega_scb *scb,
+ u_long *buffer, u_long *length);
+
+static void mega_runque(void *);
+static void mega_rundoneq(void);
+static void mega_cmd_done(mega_host_config *,mega_scb *, int);
+
+/* set SERDEBUG to 1 to enable serial debugging */
+#define SERDEBUG 0
+#if SERDEBUG
+static void ser_init(void);
+static void ser_puts(char *str);
+static void ser_putc(char c);
+static int ser_printk(const char *fmt, ...);
+#endif
+
+/*================================================================
+ *
+ * Global variables
+ *
+ *================================================================*/
+static int numCtlrs = 0;
+static mega_host_config *megaCtlrs[4] = { 0 };
+
+/* Change this to 0 if you want to see the raw drives */
+static int use_raid = 1;
+
+/* Queue of pending/completed SCBs */
+static mega_scb *qPending = NULL;
+static Scsi_Cmnd *qCompleted = NULL;
+
+volatile static spinlock_t mega_lock;
+static struct tq_struct runq = {0,0,mega_runque,NULL};
+
+struct proc_dir_entry proc_scsi_megaraid = {
+ PROC_SCSI_MEGARAID, 8, "megaraid",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+#if SERDEBUG
+static char strbuf[MAX_SERBUF+1];
+
+static void ser_init()
+{
+ unsigned port=COM_BASE;
+
+ outb(0x80,port+3);
+ outb(0,port+1);
+ /* 9600 Baud, if 19200: outb(6,port) */
+ outb(12, port);
+ outb(3,port+3);
+ outb(0,port+1);
+}
+
+static void ser_puts(char *str)
+{
+ char *ptr;
+
+ ser_init();
+ for (ptr=str;*ptr;++ptr)
+ ser_putc(*ptr);
+}
+
+static void ser_putc(char c)
+{
+ unsigned port=COM_BASE;
+
+ while ((inb(port+5) & 0x20)==0);
+ outb(c,port);
+ if (c==0x0a)
+ {
+ while ((inb(port+5) & 0x20)==0);
+ outb(0x0d,port);
+ }
+}
+
+static int ser_printk(const char *fmt, ...)
+{
+ va_list args;
+ int i;
+ long flags;
+
+ spin_lock_irqsave(mega_lock,flags);
+ va_start(args,fmt);
+ i = vsprintf(strbuf,fmt,args);
+ ser_puts(strbuf);
+ va_end(args);
+ spin_unlock_irqrestore(&mega_lock,flags);
+
+ return i;
+}
+
+#define TRACE(a) { ser_printk a;}
+
+#else
+#define TRACE(A)
+#endif
+
+void callDone(Scsi_Cmnd *SCpnt)
+{
+ if (SCpnt->result) {
+ TRACE(("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
+ SCpnt->cmnd[0], SCpnt->channel, SCpnt->target, SCpnt->lun,
+ SCpnt->result));
+ }
+ SCpnt->scsi_done(SCpnt);
+}
+
+/*-------------------------------------------------------------------------
+ *
+ * Local functions
+ *
+ *-------------------------------------------------------------------------*/
+
+/*================================================
+ * Initialize SCB structures
+ *================================================*/
+static void initSCB(mega_host_config *megaCfg)
+{
+ int idx;
+
+ for(idx=0; idx<megaCfg->max_cmds; idx++) {
+ megaCfg->scbList[idx].idx = -1;
+ megaCfg->scbList[idx].flag = 0;
+ megaCfg->scbList[idx].sgList = NULL;
+ megaCfg->scbList[idx].SCpnt = NULL;
+ }
+}
+
+/*===========================
+ * Allocate a SCB structure
+ *===========================*/
+static mega_scb *allocateSCB(mega_host_config *megaCfg,Scsi_Cmnd *SCpnt)
+{
+ int idx;
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
+ for(idx=0; idx<megaCfg->max_cmds; idx++) {
+ if (megaCfg->scbList[idx].idx < 0) {
+
+ /* Set Index and SCB pointer */
+ megaCfg->scbList[idx].flag = 0;
+ megaCfg->scbList[idx].idx = idx;
+ megaCfg->scbList[idx].SCpnt = SCpnt;
+ megaCfg->scbList[idx].next = NULL;
+ spin_unlock_irqrestore(&mega_lock,flags);
+
+ if (megaCfg->scbList[idx].sgList == NULL) {
+ megaCfg->scbList[idx].sgList =
+ kmalloc(sizeof(mega_sglist)*MAX_SGLIST,GFP_ATOMIC|GFP_DMA);
+ }
+
+ return &megaCfg->scbList[idx];
+ }
+ }
+ spin_unlock_irqrestore(&mega_lock,flags);
+
+ printk(KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
+
+ return NULL;
+}
+
+/*=======================
+ * Free a SCB structure
+ *=======================*/
+static void freeSCB(mega_scb *scb)
+{
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
+ scb->flag = 0;
+ scb->idx = -1;
+ scb->next = NULL;
+ scb->SCpnt = NULL;
+ spin_unlock_irqrestore(&mega_lock,flags);
+}
+
+/* Run through the list of completed requests */
+static void mega_rundoneq()
+{
+ mega_host_config *megaCfg;
+ Scsi_Cmnd *SCpnt;
+ long islogical;
+
+ while(1) {
+ DEQUEUE(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ if (SCpnt == NULL) return;
+
+ megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+
+ /* Check if we're allowing access to RAID drives or physical
+ * if use_raid == 1 and this wasn't a disk on the max channel or
+ * if use_raid == 0 and this was a disk on the max channel
+ * then fail.
+ */
+ islogical = (SCpnt->channel == megaCfg->host->max_channel) ? 1 : 0;
+ if (SCpnt->cmnd[0] == INQUIRY &&
+ ((((u_char*)SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
+ (islogical != use_raid)) {
+ SCpnt->result = 0xF0;
+ }
+
+ /* Convert result to error */
+ switch(SCpnt->result) {
+ case 0x00: case 0x02:
+ SCpnt->result |= (DID_OK << 16);
+ break;
+ case 0x8:
+ SCpnt->result |= (DID_BUS_BUSY << 16);
+ break;
+ default:
+ SCpnt->result |= (DID_BAD_TARGET << 16);
+ break;
+ }
+
+ /* Callback */
+ callDone(SCpnt);
+ }
+}
+
+/* Add command to the list of completed requests */
+static void mega_cmd_done(mega_host_config *megaCfg,mega_scb *pScb, int status)
+{
+ pScb->SCpnt->result = status;
+ ENQUEUE(pScb->SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+ freeSCB(pScb);
+}
+
+/*----------------------------------------------------
+ * Process pending queue list
+ *
+ * Run as a scheduled task
+ *----------------------------------------------------*/
+static void mega_runque(void *dummy)
+{
+ mega_host_config *megaCfg;
+ mega_scb *pScb;
+ long flags;
+
+ /* Take care of any completed requests */
+ mega_rundoneq();
+
+ DEQUEUE(pScb,mega_scb,qPending,next);
+
+ if (pScb) {
+ megaCfg = (mega_host_config *)pScb->SCpnt->host->hostdata;
+
+ if (megaCfg->mbox->busy || megaCfg->flag & (IN_ISR|PENDING)) {
+ TRACE(("%.08lx %.02x <%d.%d.%d> intr%d busy%d isr%d pending%d\n",
+ pScb->SCpnt->serial_number,
+ pScb->SCpnt->cmnd[0],
+ pScb->SCpnt->channel,
+ pScb->SCpnt->target,
+ pScb->SCpnt->lun,
+ intr_count,
+ megaCfg->mbox->busy,
+ (megaCfg->flag & IN_ISR) ? 1 : 0,
+ (megaCfg->flag & PENDING) ? 1 : 0));
+ }
+
+ if (MegaIssueCmd(megaCfg, pScb->mboxData, pScb, 1)) {
+ /* We're BUSY... come back later */
+ spin_lock_irqsave(&mega_lock,flags);
+ pScb->next = qPending;
+ qPending = pScb;
+ spin_unlock_irqrestore(&mega_lock,flags);
+
+ if (!(megaCfg->flag & PENDING)) { /* If PENDING, irq will schedule task */
+ queue_task(&runq, &tq_scheduler);
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------
+ *
+ * Build a SCB from a Scsi_Cmnd
+ *
+ * Returns a SCB pointer, or NULL
+ * If NULL is returned, the scsi_done function MUST have been called
+ *
+ *-------------------------------------------------------------------*/
+static mega_scb *mega_build_cmd(mega_host_config *megaCfg, Scsi_Cmnd *SCpnt)
+{
+ mega_scb *pScb;
+ mega_mailbox *mbox;
+ mega_passthru *pthru;
+ long seg;
+
+ /* We don't support multi-luns */
+ if (SCpnt->lun != 0) {
+ SCpnt->result = (DID_BAD_TARGET << 16);
+ callDone(SCpnt);
+ return NULL;
+ }
+
+ /*-----------------------------------------------------
+ *
+ * Logical drive commands
+ *
+ *-----------------------------------------------------*/
+ if (SCpnt->channel == megaCfg->host->max_channel) {
+ switch(SCpnt->cmnd[0]) {
+ case TEST_UNIT_READY:
+ memset(SCpnt->request_buffer, 0, SCpnt->request_bufflen);
+ SCpnt->result = (DID_OK << 16);
+ callDone(SCpnt);
+ return NULL;
+
+ case MODE_SENSE:
+ memset(SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
+ SCpnt->result = (DID_OK << 16);
+ callDone(SCpnt);
+ return NULL;
+
+ case READ_CAPACITY:
+ case INQUIRY:
+ /* Allocate a SCB and initialize passthru */
+ if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+ SCpnt->result = (DID_ERROR << 16);
+ callDone(SCpnt);
+ return NULL;
+ }
+ pthru = &pScb->pthru;
+ mbox = (mega_mailbox *)&pScb->mboxData;
+
+ memset(mbox, 0, sizeof(pScb->mboxData));
+ memset(pthru, 0, sizeof(mega_passthru));
+ pthru->timeout = 0;
+ pthru->ars = 0;
+ pthru->islogical = 1;
+ pthru->logdrv = SCpnt->target;
+ pthru->cdblen = SCpnt->cmd_len;
+ pthru->dataxferaddr = virt_to_bus(SCpnt->request_buffer);
+ pthru->dataxferlen = SCpnt->request_bufflen;
+ memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+ /* Initialize mailbox area */
+ mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
+ mbox->xferaddr = virt_to_bus(pthru);
+
+ return pScb;
+
+ case READ_6:
+ case WRITE_6:
+ case READ_10:
+ case WRITE_10:
+ /* Allocate a SCB and initialize mailbox */
+ if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+ SCpnt->result = (DID_ERROR << 16);
+ callDone(SCpnt);
+ return NULL;
+ }
+ mbox = (mega_mailbox *)&pScb->mboxData;
+
+ memset(mbox, 0, sizeof(pScb->mboxData));
+ mbox->logdrv = SCpnt->target;
+ mbox->cmd = (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10) ?
+ MEGA_MBOXCMD_LREAD : MEGA_MBOXCMD_LWRITE;
+
+ /* 6-byte */
+ if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
+ mbox->numsectors =
+ (u_long)SCpnt->cmnd[4];
+ mbox->lba =
+ ((u_long)SCpnt->cmnd[1] << 16) |
+ ((u_long)SCpnt->cmnd[2] << 8) |
+ (u_long)SCpnt->cmnd[3];
+ mbox->lba &= 0x1FFFFF;
+ }
+
+ /* 10-byte */
+ if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
+ mbox->numsectors =
+ (u_long)SCpnt->cmnd[8] |
+ ((u_long)SCpnt->cmnd[7] << 8);
+ mbox->lba =
+ ((u_long)SCpnt->cmnd[2] << 24) |
+ ((u_long)SCpnt->cmnd[3] << 16) |
+ ((u_long)SCpnt->cmnd[4] << 8) |
+ (u_long)SCpnt->cmnd[5];
+ }
+
+ /* Calculate Scatter-Gather info */
+ mbox->numsgelements = build_sglist(megaCfg, pScb,
+ (u_long*)&mbox->xferaddr,
+ (u_long*)&seg);
+
+ return pScb;
+
+ default:
+ SCpnt->result = (DID_BAD_TARGET << 16);
+ callDone(SCpnt);
+ return NULL;
+ }
+ }
+ /*-----------------------------------------------------
+ *
+ * Passthru drive commands
+ *
+ *-----------------------------------------------------*/
+ else {
+ /* Allocate a SCB and initialize passthru */
+ if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+ SCpnt->result = (DID_ERROR << 16);
+ callDone(SCpnt);
+ return NULL;
+ }
+ pthru = &pScb->pthru;
+ mbox = (mega_mailbox *)pScb->mboxData;
+
+ memset(mbox, 0, sizeof(pScb->mboxData));
+ memset(pthru, 0, sizeof(mega_passthru));
+ pthru->timeout = 0;
+ pthru->ars = 0;
+ pthru->islogical = 0;
+ pthru->channel = SCpnt->channel;
+ pthru->target = SCpnt->target;
+ pthru->cdblen = SCpnt->cmd_len;
+ memcpy(pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
+
+ pthru->numsgelements = build_sglist(megaCfg, pScb,
+ (u_long *)&pthru->dataxferaddr,
+ (u_long *)&pthru->dataxferlen);
+
+ /* Initialize mailbox */
+ mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
+ mbox->xferaddr = virt_to_bus(pthru);
+
+ return pScb;
+ }
+ return NULL;
+}
+
+/*--------------------------------------------------------------------
+ * Interrupt service routine
+ *--------------------------------------------------------------------*/
+static void megaraid_isr(int irq, void *devp, struct pt_regs *regs)
+{
+ mega_host_config *megaCfg;
+ u_char byte, idx, sIdx;
+ u_long dword;
+ mega_mailbox *mbox;
+ mega_scb *pScb;
+ long flags;
+ int qCnt, qStatus;
+
+ megaCfg = (mega_host_config *)devp;
+ mbox = (mega_mailbox *)megaCfg->mbox;
+
+ if (megaCfg->host->irq == irq) {
+ spin_lock_irqsave(&mega_lock,flags);
+
+ if (megaCfg->flag & IN_ISR) {
+ TRACE(("ISR called reentrantly!!\n"));
+ }
+
+ megaCfg->flag |= IN_ISR;
+
+ /* Check if a valid interrupt is pending */
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ dword = RDOUTDOOR(megaCfg);
+ if (dword != 0x10001234) {
+ /* Spurious interrupt */
+ megaCfg->flag &= ~IN_ISR;
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return;
+ }
+ WROUTDOOR(megaCfg,dword);
+ } else {
+ byte = READ_PORT(megaCfg->host->io_port, INTR_PORT);
+ if ((byte & VALID_INTR_BYTE) == 0) {
+ /* Spurious interrupt */
+ megaCfg->flag &= ~IN_ISR;
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return;
+ }
+ WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte);
+ }
+
+ qCnt = mbox->numstatus;
+ qStatus = mbox->status;
+
+ if (qCnt > 1) {TRACE(("ISR: Received %d status\n", qCnt))
+ printk(KERN_DEBUG "Got numstatus = %d\n",qCnt);
+ }
+
+ for(idx=0; idx<qCnt; idx++) {
+ sIdx = mbox->completed[idx];
+ if (sIdx > 0) {
+ pScb = &megaCfg->scbList[sIdx-1];
+ spin_unlock_irqrestore(&mega_lock,flags); /* locks within cmd_done */
+ mega_cmd_done(megaCfg,&megaCfg->scbList[sIdx-1], qStatus);
+ spin_lock_irqsave(&mega_lock,flags);
+ }
+ }
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox)|0x2);
+ while (RDINDOOR(megaCfg) & 0x02);
+ } else {
+ CLEAR_INTR(megaCfg->host->io_port);
+ }
+
+ megaCfg->flag &= ~IN_ISR;
+ megaCfg->flag &= ~PENDING;
+
+ spin_unlock_irqrestore(&mega_lock,flags);
+
+ spin_lock_irqsave(&io_request_lock, flags);
+ mega_runque(NULL);
+ spin_unlock_irqrestore(&io_request_lock,flags);
+
+#if 0
+ /* Queue as a delayed ISR routine */
+ queue_task_irq_off(&runq, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
+ spin_unlock_irqrestore(&mega_lock,flags);
+#endif
+
+ }
+}
+
+/*==================================================*/
+/* Wait until the controller's mailbox is available */
+/*==================================================*/
+static int busyWaitMbox(mega_host_config *megaCfg)
+{
+ mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
+ long counter;
+
+ for(counter=0; counter<0xFFFFFF; counter++) {
+ if (!mbox->busy) return 0;
+ }
+ return -1;
+}
+
+/*=====================================================
+ * Post a command to the card
+ *
+ * Arguments:
+ * mega_host_config *megaCfg - Controller structure
+ * u_char *mboxData - Mailbox area, 16 bytes
+ * mega_scb *pScb - SCB posting (or NULL if N/A)
+ * int intr - if 1, interrupt, 0 is blocking
+ *=====================================================*/
+static int MegaIssueCmd(mega_host_config *megaCfg,
+ u_char *mboxData,
+ mega_scb *pScb,
+ int intr)
+{
+ mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
+ long flags;
+ u_char byte;
+ u_long cmdDone;
+
+ mboxData[0x1] = (pScb ? pScb->idx+1 : 0x00); /* Set cmdid */
+ mboxData[0xF] = 1; /* Set busy */
+
+ /* one bad report of problem when issuing a command while pending.
+ * Wasn't able to duplicate, but it doesn't really affect performance
+ * anyway, so don't allow command while PENDING
+ */
+ if (megaCfg->flag & PENDING) {
+ return -1;
+ }
+
+ /* Wait until mailbox is free */
+ if (busyWaitMbox(megaCfg)) {
+ if (pScb) {
+ TRACE(("Mailbox busy %.08lx <%d.%d.%d>\n", pScb->SCpnt->serial_number,
+ pScb->SCpnt->channel, pScb->SCpnt->target, pScb->SCpnt->lun));
+ }
+ return -1;
+ }
+
+ /* Copy mailbox data into host structure */
+ spin_lock_irqsave(&mega_lock,flags);
+ memset(mbox, 0, sizeof(mega_mailbox));
+ memcpy(mbox, mboxData, 16);
+ spin_unlock_irqrestore(&mega_lock,flags);
+
+ /* Kick IO */
+ megaCfg->flag |= PENDING;
+ if (intr) {
+ /* Issue interrupt (non-blocking) command */
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ mbox->mraid_poll = 0;
+ mbox->mraid_ack = 0;
+ WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1);
+ } else {
+ ENABLE_INTR(megaCfg->host->io_port);
+ ISSUE_COMMAND(megaCfg->host->io_port);
+ }
+ }
+ else { /* Issue non-ISR (blocking) command */
+
+ if (megaCfg->flag & BOARD_QUARTZ) {
+
+ mbox->mraid_poll = 0;
+ mbox->mraid_ack = 0;
+ WRINDOOR(megaCfg, virt_to_bus(megaCfg->mbox) | 0x1);
+
+ while((cmdDone=RDOUTDOOR(megaCfg)) != 0x10001234);
+ WROUTDOOR(megaCfg, cmdDone);
+
+ if (pScb) {
+ mega_cmd_done(megaCfg,pScb, mbox->status);
+ mega_rundoneq();
+ }
+
+ WRINDOOR(megaCfg,virt_to_bus(megaCfg->mbox) | 0x2);
+ while(RDINDOOR(megaCfg) & 0x2);
+
+ megaCfg->flag &= ~PENDING;
+ }
+ else {
+ DISABLE_INTR(megaCfg->host->io_port);
+ ISSUE_COMMAND(megaCfg->host->io_port);
+
+ while(!((byte=READ_PORT(megaCfg->host->io_port,INTR_PORT))&INTR_VALID));
+ WRITE_PORT(megaCfg->host->io_port, INTR_PORT, byte);
+
+ ENABLE_INTR(megaCfg->host->io_port);
+ CLEAR_INTR(megaCfg->host->io_port);
+
+ if (pScb) {
+ mega_cmd_done(megaCfg,pScb, mbox->status);
+ mega_rundoneq();
+ }
+ megaCfg->flag &= ~PENDING;
+ }
+ }
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------
+ * Copies data to SGLIST
+ *-------------------------------------------------------------------*/
+static int build_sglist(mega_host_config *megaCfg, mega_scb *scb,
+ u_long *buffer, u_long *length)
+{
+ struct scatterlist *sgList;
+ int idx;
+
+ /* Scatter-gather not used */
+ if (scb->SCpnt->use_sg == 0) {
+ *buffer = virt_to_bus(scb->SCpnt->request_buffer);
+ *length = (u_long)scb->SCpnt->request_bufflen;
+ return 0;
+ }
+
+ sgList = (struct scatterlist *)scb->SCpnt->buffer;
+ if (scb->SCpnt->use_sg == 1) {
+ *buffer = virt_to_bus(sgList[0].address);
+ *length = (u_long)sgList[0].length;
+ return 0;
+ }
+
+ /* Copy Scatter-Gather list info into controller structure */
+ for(idx=0; idx<scb->SCpnt->use_sg; idx++) {
+ scb->sgList[idx].address = virt_to_bus(sgList[idx].address);
+ scb->sgList[idx].length = (u_long)sgList[idx].length;
+ }
+
+ /* Reset pointer and length fields */
+ *buffer = virt_to_bus(scb->sgList);
+ *length = 0;
+
+ /* Return count of SG requests */
+ return scb->SCpnt->use_sg;
+}
+
+/*--------------------------------------------------------------------
+ * Initializes the address of the controller's mailbox register
+ * The mailbox register is used to issue commands to the card.
+ * Format of the mailbox area:
+ * 00 01 command
+ * 01 01 command id
+ * 02 02 # of sectors
+ * 04 04 logical bus address
+ * 08 04 physical buffer address
+ * 0C 01 logical drive #
+ * 0D 01 length of scatter/gather list
+ * 0E 01 reserved
+ * 0F 01 mailbox busy
+ * 10 01 numstatus byte
+ * 11 01 status byte
+ *--------------------------------------------------------------------*/
+static int mega_register_mailbox(mega_host_config *megaCfg, u_long paddr)
+{
+ /* align on 16-byte boundry */
+ megaCfg->mbox = &megaCfg->mailbox;
+ megaCfg->mbox = (mega_mailbox *) ((((ulong)megaCfg->mbox) + 16)&0xfffffff0);
+ paddr = (paddr+16)&0xfffffff0;
+
+ /* Register mailbox area with the firmware */
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ }
+ else {
+ WRITE_PORT(megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
+ WRITE_PORT(megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
+ WRITE_PORT(megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
+ WRITE_PORT(megaCfg->host->io_port, MBOX_PORT3, (paddr >> 24) & 0xFF);
+ WRITE_PORT(megaCfg->host->io_port, ENABLE_MBOX_REGION, ENABLE_MBOX_BYTE);
+
+ CLEAR_INTR(megaCfg->host->io_port);
+ ENABLE_INTR(megaCfg->host->io_port);
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------------------
+ * Issue an adapter info query to the controller
+ *-------------------------------------------------------------------*/
+static int mega_i_query_adapter(mega_host_config *megaCfg)
+{
+ mega_RAIDINQ *adapterInfo;
+ mega_mailbox *mbox;
+ u_char mboxData[16];
+ u_long paddr;
+
+ spin_lock_init(&mega_lock);
+ /* Initialize adapter inquiry */
+ paddr = virt_to_bus(megaCfg->mega_buffer);
+ mbox = (mega_mailbox *)mboxData;
+
+ memset((void *)megaCfg->mega_buffer, 0, sizeof(megaCfg->mega_buffer));
+ memset(mbox, 0, 16);
+
+ /* Initialize mailbox registers */
+ mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;
+ mbox->xferaddr = paddr;
+
+ /* Issue a blocking command to the card */
+ MegaIssueCmd(megaCfg, mboxData, NULL, 0);
+
+ /* Initialize host/local structures with Adapter info */
+ adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer;
+ megaCfg->host->max_channel = adapterInfo->AdpInfo.ChanPresent;
+ megaCfg->host->max_id = adapterInfo->AdpInfo.MaxTargPerChan;
+ megaCfg->numldrv = adapterInfo->LogdrvInfo.NumLDrv;
+
+#if 0
+ printk(KERN_DEBUG "---- Logical drive info ----\n");
+ for(i=0; i<megaCfg->numldrv; i++) {
+ printk(KERN_DEBUG "%d: size: %ld prop: %x state: %x\n",i,
+ adapterInfo->LogdrvInfo.LDrvSize[i],
+ adapterInfo->LogdrvInfo.LDrvProp[i],
+ adapterInfo->LogdrvInfo.LDrvState[i]);
+ }
+ printk(KERN_DEBUG "---- Physical drive info ----\n");
+ for(i=0; i<MAX_PHYSICAL_DRIVES; i++) {
+ if (i && !(i % 8)) printk("\n");
+ printk("%d: %x ", i, adapterInfo->PhysdrvInfo.PDrvState[i]);
+ }
+ printk("\n");
+#endif
+
+ megaCfg->max_cmds = adapterInfo->AdpInfo.MaxConcCmds;
+
+#ifdef HP /* use HP firmware and bios version encoding */
+ sprintf(megaCfg->fwVer,"%c%d%d.%d%d",
+ adapterInfo->AdpInfo.FwVer[2],
+ adapterInfo->AdpInfo.FwVer[1] >> 8,
+ adapterInfo->AdpInfo.FwVer[1] & 0x0f,
+ adapterInfo->AdpInfo.FwVer[2] >> 8,
+ adapterInfo->AdpInfo.FwVer[2] & 0x0f);
+ sprintf(megaCfg->biosVer,"%c%d%d.%d%d",
+ adapterInfo->AdpInfo.BiosVer[2],
+ adapterInfo->AdpInfo.BiosVer[1] >> 8,
+ adapterInfo->AdpInfo.BiosVer[1] & 0x0f,
+ adapterInfo->AdpInfo.BiosVer[2] >> 8,
+ adapterInfo->AdpInfo.BiosVer[2] & 0x0f);
+#else
+ memcpy(megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
+ megaCfg->fwVer[4] = 0;
+
+ memcpy(megaCfg->biosVer, adapterInfo->AdpInfo.BiosVer, 4);
+ megaCfg->biosVer[4] = 0;
+#endif
+
+ printk(KERN_INFO "megaraid: [%s:%s] detected %d logical drives" CRLFSTR,
+ megaCfg->fwVer,
+ megaCfg->biosVer,
+ megaCfg->numldrv);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------
+ *
+ * Driver interface functions
+ *
+ *-------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------
+ * Returns data to be displayed in /proc/scsi/megaraid/X
+ *----------------------------------------------------------*/
+int megaraid_proc_info(char *buffer, char **start, off_t offset,
+ int length, int inode, int inout)
+{
+ *start = buffer;
+ return 0;
+}
+
+int findCard(Scsi_Host_Template *pHostTmpl,
+ u_short pciVendor, u_short pciDev,
+ long flag)
+{
+ mega_host_config *megaCfg;
+ struct Scsi_Host *host;
+ u_char pciBus, pciDevFun, megaIrq;
+ u_long megaBase;
+ u_short pciIdx = 0;
+
+#if LINUX_VERSION_CODE < 0x20100
+ while(!pcibios_find_device(pciVendor, pciDev, pciIdx,&pciBus,&pciDevFun)) {
+#else
+ struct pci_dev *pdev=pci_devices;
+
+ while((pdev = pci_find_device(pciVendor, pciDev, pdev))) {
+ pciBus = pdev->bus->number;
+ pciDevFun = pdev->devfn;
+#endif
+ printk(KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:fun %d\n",
+ pciVendor,
+ pciDev,
+ pciIdx, pciBus,
+ PCI_SLOT(pciDevFun),
+ PCI_FUNC(pciDevFun));
+
+ /* Read the base port and IRQ from PCI */
+#if LINUX_VERSION_CODE < 0x20100
+ pcibios_read_config_dword(pciBus, pciDevFun,
+ PCI_BASE_ADDRESS_0,
+ (u_int *)&megaBase);
+ pcibios_read_config_byte(pciBus, pciDevFun,
+ PCI_INTERRUPT_LINE,
+ &megaIrq);
+#else
+ megaBase = pdev->base_address[0];
+ megaIrq = pdev->irq;
+#endif
+ pciIdx++;
+
+ if (flag & BOARD_QUARTZ) {
+ megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
+ megaBase = (long) ioremap(megaBase,128);
+ }
+ else {
+ megaBase &= PCI_BASE_ADDRESS_IO_MASK;
+ megaBase += 0x10;
+ }
+
+ /* Initialize SCSI Host structure */
+ host = scsi_register(pHostTmpl, sizeof(mega_host_config));
+ megaCfg = (mega_host_config *)host->hostdata;
+ memset(megaCfg, 0, sizeof(mega_host_config));
+
+ printk(KERN_INFO " scsi%d: Found a MegaRAID controller at 0x%x, IRQ: %d" CRLFSTR,
+ host->host_no, (u_int)megaBase, megaIrq);
+
+ /* Copy resource info into structure */
+ megaCfg->flag = flag;
+ megaCfg->host = host;
+ megaCfg->base = megaBase;
+ megaCfg->host->irq = megaIrq;
+ megaCfg->host->io_port = megaBase;
+ megaCfg->host->n_io_port = 16;
+ megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
+ megaCtlrs[numCtlrs++] = megaCfg;
+
+ if (flag != BOARD_QUARTZ) {
+ /* Request our IO Range */
+ if (check_region(megaBase, 16)) {
+ printk(KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR);
+ scsi_unregister(host);
+ continue;
+ }
+ request_region(megaBase, 16, "megaraid");
+ }
+
+ /* Request our IRQ */
+ if (request_irq(megaIrq, megaraid_isr, SA_SHIRQ,
+ "megaraid", megaCfg)) {
+ printk(KERN_WARNING "megaraid: Couldn't register IRQ %d!" CRLFSTR,
+ megaIrq);
+ scsi_unregister(host);
+ continue;
+ }
+
+ mega_register_mailbox(megaCfg, virt_to_bus((void*)&megaCfg->mailbox));
+ mega_i_query_adapter(megaCfg);
+
+ /* Initialize SCBs */
+ initSCB(megaCfg);
+
+ }
+ return pciIdx;
+}
+
+/*---------------------------------------------------------
+ * Detects if a megaraid controller exists in this system
+ *---------------------------------------------------------*/
+int megaraid_detect(Scsi_Host_Template *pHostTmpl)
+{
+ int count = 0;
+
+ pHostTmpl->proc_dir = &proc_scsi_megaraid;
+
+#if LINUX_VERSION_CODE < 0x20100
+ if (!pcibios_present())
+ {
+ printk(KERN_WARNING "megaraid: PCI bios not present." CRLFSTR);
+ return 0;
+ }
+#endif
+
+ count += findCard(pHostTmpl, 0x101E, 0x9010, 0);
+ count += findCard(pHostTmpl, 0x101E, 0x9060, 0);
+ count += findCard(pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+
+ return count;
+}
+
+/*---------------------------------------------------------------------
+ * Release the controller's resources
+ *---------------------------------------------------------------------*/
+int megaraid_release(struct Scsi_Host *pSHost)
+{
+ mega_host_config *megaCfg;
+ mega_mailbox *mbox;
+ u_char mboxData[16];
+
+ megaCfg = (mega_host_config*)pSHost->hostdata;
+ mbox = (mega_mailbox *)mboxData;
+
+ /* Flush cache to disk */
+ memset(mbox, 0, 16);
+ mboxData[0] = 0xA;
+
+ /* Issue a blocking (interrupts disabled) command to the card */
+ MegaIssueCmd(megaCfg, mboxData, NULL, 0);
+
+ schedule();
+
+ /* Free our resources */
+ if (megaCfg->flag & BOARD_QUARTZ) {
+ iounmap((void *)megaCfg->base);
+ } else {
+ release_region(megaCfg->host->io_port, 16);
+ }
+ free_irq(megaCfg->host->irq, megaCfg); /* Must be freed first, otherwise
+ extra interrupt is generated */
+ scsi_unregister(pSHost);
+
+ return 0;
+}
+
+/*----------------------------------------------
+ * Get information about the card/driver
+ *----------------------------------------------*/
+const char *megaraid_info(struct Scsi_Host *pSHost)
+{
+ static char buffer[512];
+ mega_host_config *megaCfg;
+ mega_RAIDINQ *adapterInfo;
+
+ megaCfg = (mega_host_config *)pSHost->hostdata;
+ adapterInfo = (mega_RAIDINQ *)megaCfg->mega_buffer;
+
+ sprintf(buffer, "AMI MegaRAID %s %d commands %d targs %d chans",
+ megaCfg->fwVer,
+ adapterInfo->AdpInfo.MaxConcCmds,
+ megaCfg->host->max_id,
+ megaCfg->host->max_channel);
+ return buffer;
+}
+
+/*-----------------------------------------------------------------
+ * Perform a SCSI command
+ * Mailbox area:
+ * 00 01 command
+ * 01 01 command id
+ * 02 02 # of sectors
+ * 04 04 logical bus address
+ * 08 04 physical buffer address
+ * 0C 01 logical drive #
+ * 0D 01 length of scatter/gather list
+ * 0E 01 reserved
+ * 0F 01 mailbox busy
+ * 10 01 numstatus byte
+ * 11 01 status byte
+ *-----------------------------------------------------------------*/
+int megaraid_queue(Scsi_Cmnd *SCpnt, void (*pktComp)(Scsi_Cmnd *))
+{
+ mega_host_config *megaCfg;
+ mega_scb *pScb;
+
+ megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+
+ if (!(megaCfg->flag & (1L << SCpnt->channel))) {
+ printk(KERN_INFO "scsi%d: scanning channel %c for devices.\n",
+ megaCfg->host->host_no,
+ SCpnt->channel + 'A');
+ megaCfg->flag |= (1L << SCpnt->channel);
+ }
+
+ SCpnt->scsi_done = pktComp;
+
+ /* Allocate and build a SCB request */
+ if ((pScb = mega_build_cmd(megaCfg, SCpnt)) != NULL) {
+ /* Add SCB to the head of the pending queue */
+ ENQUEUE(pScb, mega_scb, qPending, next);
+
+ /* Issue the command to the card */
+ mega_runque(NULL);
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------
+ * Issue a blocking command to the controller
+ *
+ * Note - this isnt 2.0.x SMP safe
+ *----------------------------------------------------------------------*/
+volatile static int internal_done_flag = 0;
+volatile static int internal_done_errcode = 0;
+
+static void internal_done(Scsi_Cmnd *SCpnt)
+{
+ internal_done_errcode = SCpnt->result;
+ internal_done_flag++;
+}
+
+/*
+ * This seems dangerous in an SMP environment because
+ * while spinning on internal_done_flag in 2.0.x SMP
+ * no IRQ's will be taken, including those that might
+ * be needed to clear this.
+ *
+ * I think this should be using a wait queue ?
+ * -- AC
+ */
+
+int megaraid_command(Scsi_Cmnd *SCpnt)
+{
+ internal_done_flag = 0;
+
+ /* Queue command, and wait until it has completed */
+ megaraid_queue(SCpnt, internal_done);
+
+ while(!internal_done_flag)
+ barrier();
+
+ return internal_done_errcode;
+}
+
+/*---------------------------------------------------------------------
+ * Abort a previous SCSI request
+ *---------------------------------------------------------------------*/
+int megaraid_abort(Scsi_Cmnd *SCpnt)
+{
+ mega_host_config *megaCfg;
+ int idx;
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
+
+ megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+
+ TRACE(("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
+ SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+ SCpnt->lun));
+ /*
+ * Walk list of SCBs for any that are still outstanding
+ */
+ for(idx=0; idx<megaCfg->max_cmds; idx++) {
+ if (megaCfg->scbList[idx].idx >= 0) {
+ if (megaCfg->scbList[idx].SCpnt == SCpnt) {
+ freeSCB(&megaCfg->scbList[idx]);
+
+ SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
+ callDone(SCpnt);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return SCSI_ABORT_SNOOZE;
+}
+
+/*---------------------------------------------------------------------
+ * Reset a previous SCSI request
+ *---------------------------------------------------------------------*/
+int megaraid_reset(Scsi_Cmnd *SCpnt, unsigned int rstflags)
+{
+ mega_host_config *megaCfg;
+ int idx;
+ long flags;
+
+ spin_lock_irqsave(&mega_lock,flags);
+
+ megaCfg = (mega_host_config *)SCpnt->host->hostdata;
+
+ TRACE(("RESET: %.08lx %.02x <%d.%d.%d>\n",
+ SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+ SCpnt->lun));
+
+ /*
+ * Walk list of SCBs for any that are still outstanding
+ */
+ for(idx=0; idx<megaCfg->max_cmds; idx++) {
+ if (megaCfg->scbList[idx].idx >= 0) {
+ SCpnt = megaCfg->scbList[idx].SCpnt;
+ freeSCB(&megaCfg->scbList[idx]);
+ SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
+ callDone(SCpnt);
+ }
+ }
+ spin_unlock_irqrestore(&mega_lock,flags);
+ return SCSI_RESET_PUNT;
+}
+
+/*-------------------------------------------------------------
+ * Return the disk geometry for a particular disk
+ * Input:
+ * Disk *disk - Disk geometry
+ * kdev_t dev - Device node
+ * int *geom - Returns geometry fields
+ * geom[0] = heads
+ * geom[1] = sectors
+ * geom[2] = cylinders
+ *-------------------------------------------------------------*/
+int megaraid_biosparam(Disk *disk, kdev_t dev, int *geom)
+{
+ int heads, sectors, cylinders;
+ mega_host_config *megaCfg;
+
+ /* Get pointer to host config structure */
+ megaCfg = (mega_host_config *)disk->device->host->hostdata;
+
+ /* Default heads (64) & sectors (32) */
+ heads = 64;
+ sectors = 32;
+ cylinders = disk->capacity / (heads * sectors);
+
+ /* Handle extended translation size for logical drives > 1Gb */
+ if (disk->capacity >= 0x200000) {
+ heads = 255;
+ sectors = 63;
+ cylinders = disk->capacity / (heads * sectors);
+ }
+
+ /* return result */
+ geom[0] = heads;
+ geom[1] = sectors;
+ geom[2] = cylinders;
+
+ return 0;
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = MEGARAID;
+
+#include "scsi_module.c"
+#endif
diff --git a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h
new file mode 100644
index 000000000..b020d1b78
--- /dev/null
+++ b/drivers/scsi/megaraid.h
@@ -0,0 +1,284 @@
+#ifndef __MEGARAID_H__
+#define __MEGARAID_H__
+
+#include <linux/version.h>
+
+#define IN_ISR 0x80000000L
+#define NO_INTR 0x40000000L
+#define IN_TIMEOUT 0x20000000L
+#define PENDING 0x10000000L
+#define BOARD_QUARTZ 0x08000000L
+
+#define SCB_ACTIVE 0x1
+#define SCB_WAITQ 0x2
+#define SCB_ISSUED 0x4
+
+#define SCB_FREE -1
+#define SCB_RESET -2
+#define SCB_ABORT -3
+#define SCB_LOCKED -4
+
+#define MEGA_CMD_TIMEOUT 10
+
+#define MAX_SGLIST 20
+#define MAX_COMMANDS 254
+
+#define MAX_LOGICAL_DRIVES 8
+#define MAX_CHANNEL 5
+#define MAX_TARGET 15
+#define MAX_PHYSICAL_DRIVES MAX_CHANNEL*MAX_TARGET
+
+#define INQUIRY_DATA_SIZE 0x24
+#define MAX_CDB_LEN 0x0A
+#define MAX_REQ_SENSE_LEN 0x20
+
+#define INTR_VALID 0x40
+
+/* Mailbox commands */
+#define MEGA_MBOXCMD_LREAD 0x01
+#define MEGA_MBOXCMD_LWRITE 0x02
+#define MEGA_MBOXCMD_PASSTHRU 0x03
+#define MEGA_MBOXCMD_ADAPTERINQ 0x05
+
+/* Offsets into Mailbox */
+#define COMMAND_PORT 0x00
+#define COMMAND_ID_PORT 0x01
+#define SG_LIST_PORT0 0x08
+#define SG_LIST_PORT1 0x09
+#define SG_LIST_PORT2 0x0a
+#define SG_LIST_PORT3 0x0b
+#define SG_ELEMENT_PORT 0x0d
+#define NO_FIRED_PORT 0x0f
+
+/* I/O Port offsets */
+#define I_CMD_PORT 0x00
+#define I_ACK_PORT 0x00
+#define I_TOGGLE_PORT 0x01
+#define INTR_PORT 0x0a
+
+#define MAILBOX_SIZE 70
+#define MBOX_BUSY_PORT 0x00
+#define MBOX_PORT0 0x04
+#define MBOX_PORT1 0x05
+#define MBOX_PORT2 0x06
+#define MBOX_PORT3 0x07
+#define ENABLE_MBOX_REGION 0x0B
+
+/* I/O Port Values */
+#define ISSUE_BYTE 0x10
+#define ACK_BYTE 0x08
+#define ENABLE_INTR_BYTE 0xc0
+#define DISABLE_INTR_BYTE 0x00
+#define VALID_INTR_BYTE 0x40
+#define MBOX_BUSY_BYTE 0x10
+#define ENABLE_MBOX_BYTE 0x00
+
+/* Setup some port macros here */
+#define WRITE_MAILBOX(base,offset,value) *(base+offset)=value
+#define READ_MAILBOX(base,offset) *(base+offset)
+
+#define WRITE_PORT(base,offset,value) outb_p(value,base+offset)
+#define READ_PORT(base,offset) inb_p(base+offset)
+
+#define ISSUE_COMMAND(base) WRITE_PORT(base,I_CMD_PORT,ISSUE_BYTE)
+#define CLEAR_INTR(base) WRITE_PORT(base,I_ACK_PORT,ACK_BYTE)
+#define ENABLE_INTR(base) WRITE_PORT(base,I_TOGGLE_PORT,ENABLE_INTR_BYTE)
+#define DISABLE_INTR(base) WRITE_PORT(base,I_TOGGLE_PORT,DISABLE_INTR_BYTE)
+
+/* Define AMI's PCI codes */
+#undef PCI_VENDOR_ID_AMI
+#undef PCI_DEVICE_ID_AMI_MEGARAID
+
+#ifndef PCI_VENDOR_ID_AMI
+#define PCI_VENDOR_ID_AMI 0x101E
+#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010
+#endif
+
+#define PCI_CONF_BASE_ADDR_OFFSET 0x10
+#define PCI_CONF_IRQ_OFFSET 0x3c
+
+#if LINUX_VERSION_CODE < 0x20100
+#define MEGARAID \
+ { NULL, /* Next */\
+ NULL, /* Usage Count Pointer */\
+ NULL, /* /proc Directory Entry */\
+ megaraid_proc_info, /* /proc Info Function */\
+ "MegaRAID", /* Driver Name */\
+ megaraid_detect, /* Detect Host Adapter */\
+ megaraid_release, /* Release Host Adapter */\
+ megaraid_info, /* Driver Info Function */\
+ megaraid_command, /* Command Function */\
+ megaraid_queue, /* Queue Command Function */\
+ megaraid_abort, /* Abort Command Function */\
+ megaraid_reset, /* Reset Command Function */\
+ NULL, /* Slave Attach Function */\
+ megaraid_biosparam, /* Disk BIOS Parameters */\
+ 1, /* # of cmds that can be\
+ outstanding at any time */\
+ 7, /* HBA Target ID */\
+ MAX_SGLIST, /* Scatter/Gather Table Size */\
+ 1, /* SCSI Commands per LUN */\
+ 0, /* Present */\
+ 0, /* Default Unchecked ISA DMA */\
+ ENABLE_CLUSTERING } /* Enable Clustering */
+#else
+#define MEGARAID \
+ {\
+ name: "MegaRAID", /* Driver Name */\
+ proc_info: megaraid_proc_info, /* /proc driver info */\
+ detect: megaraid_detect, /* Detect Host Adapter */\
+ release: megaraid_release, /* Release Host Adapter */\
+ info: megaraid_info, /* Driver Info Function */\
+ command: megaraid_command, /* Command Function */\
+ queuecommand: megaraid_queue, /* Queue Command Function */\
+ abort: megaraid_abort, /* Abort Command Function */\
+ reset: megaraid_reset, /* Reset Command Function */\
+ bios_param: megaraid_biosparam, /* Disk BIOS Parameters */\
+ can_queue: 255, /* Can Queue */\
+ this_id: 7, /* HBA Target ID */\
+ sg_tablesize: MAX_SGLIST, /* Scatter/Gather Table Size */\
+ cmd_per_lun: 1, /* SCSI Commands per LUN */\
+ present: 0, /* Present */\
+ unchecked_isa_dma:0, /* Default Unchecked ISA DMA */\
+ use_clustering: ENABLE_CLUSTERING /* Enable Clustering */\
+ }
+#endif
+
+/* Structures */
+typedef struct _mega_ADP_INFO
+{
+ u_char MaxConcCmds;
+ u_char RbldRate;
+ u_char MaxTargPerChan;
+ u_char ChanPresent;
+ u_char FwVer[4];
+ u_short AgeOfFlash;
+ u_char ChipSet;
+ u_char DRAMSize;
+ u_char CacheFlushInterval;
+ u_char BiosVer[4];
+ u_char resvd[7];
+} mega_ADP_INFO;
+
+typedef struct _mega_LDRV_INFO
+{
+ u_char NumLDrv;
+ u_char resvd[3];
+ u_long LDrvSize[MAX_LOGICAL_DRIVES];
+ u_char LDrvProp[MAX_LOGICAL_DRIVES];
+ u_char LDrvState[MAX_LOGICAL_DRIVES];
+} mega_LDRV_INFO;
+
+typedef struct _mega_PDRV_INFO
+{
+ u_char PDrvState[MAX_PHYSICAL_DRIVES];
+ u_char resvd;
+} mega_PDRV_INFO;
+
+// RAID inquiry: Mailbox command 0x5
+typedef struct _mega_RAIDINQ
+{
+ mega_ADP_INFO AdpInfo;
+ mega_LDRV_INFO LogdrvInfo;
+ mega_PDRV_INFO PhysdrvInfo;
+} mega_RAIDINQ;
+
+// Passthrough command: Mailbox command 0x3
+typedef struct mega_passthru
+{
+ u_char timeout:3; /* 0=6sec/1=60sec/2=10min/3=3hrs */
+ u_char ars:1;
+ u_char reserved:3;
+ u_char islogical:1;
+ u_char logdrv; /* if islogical == 1 */
+ u_char channel; /* if islogical == 0 */
+ u_char target; /* if islogical == 0 */
+ u_char queuetag; /* unused */
+ u_char queueaction; /* unused */
+ u_char cdb[MAX_CDB_LEN];
+ u_char cdblen;
+ u_char reqsenselen;
+ u_char reqsensearea[MAX_REQ_SENSE_LEN];
+ u_char numsgelements;
+ u_char scsistatus;
+ u_long dataxferaddr;
+ u_long dataxferlen;
+} mega_passthru;
+
+typedef struct _mega_mailbox
+{
+ /* 0x0 */ u_char cmd;
+ /* 0x1 */ u_char cmdid;
+ /* 0x2 */ u_short numsectors;
+ /* 0x4 */ u_long lba;
+ /* 0x8 */ u_long xferaddr;
+ /* 0xC */ u_char logdrv;
+ /* 0xD */ u_char numsgelements;
+ /* 0xE */ u_char resvd;
+ /* 0xF */ u_char busy;
+ /* 0x10*/ u_char numstatus;
+ /* 0x11*/ u_char status;
+ /* 0x12*/ u_char completed[46];
+ u_char mraid_poll;
+ u_char mraid_ack;
+ u_char pad[16];
+} mega_mailbox;
+
+typedef struct _mega_sglist
+{
+ u_long address;
+ u_long length;
+} mega_sglist;
+
+/* Queued command data */
+typedef struct _mega_scb mega_scb;
+
+struct _mega_scb
+{
+ int idx;
+ u_long flag;
+ Scsi_Cmnd *SCpnt;
+ u_char mboxData[16];
+ mega_passthru pthru;
+ mega_sglist *sgList;
+ mega_scb *next;
+};
+
+/* Per-controller data */
+typedef struct _mega_host_config
+{
+ u_char numldrv;
+ u_long flag;
+ u_long base;
+
+ struct tq_struct megaTq;
+
+ /* Host adapter parameters */
+ u_char fwVer[7];
+ u_char biosVer[7];
+
+ struct Scsi_Host *host;
+
+ /* The following must be DMA-able!! */
+ volatile mega_mailbox *mbox;
+ volatile mega_mailbox mailbox;
+ volatile u_char mega_buffer[2*1024L];
+
+ u_char max_cmds;
+ mega_scb scbList[MAX_COMMANDS];
+} mega_host_config;
+
+extern struct proc_dir_entry proc_scsi_megaraid;
+
+const char *megaraid_info( struct Scsi_Host * );
+int megaraid_detect( Scsi_Host_Template * );
+int megaraid_release(struct Scsi_Host *);
+int megaraid_command( Scsi_Cmnd * );
+int megaraid_abort( Scsi_Cmnd * );
+int megaraid_reset( Scsi_Cmnd *, unsigned int);
+int megaraid_queue( Scsi_Cmnd *, void (*done)(Scsi_Cmnd *) );
+int megaraid_biosparam( Disk *, kdev_t, int * );
+int megaraid_proc_info( char *buffer, char **start, off_t offset,
+ int length, int hostno, int inout );
+
+#endif
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index c08589b58..316d661b5 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1346,11 +1346,11 @@ handle_reset(struct mesh_state *ms)
static void
do_mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
{
- /*unsigned long flags;*/
+ unsigned long flags;
- /*spin_lock_irqsave(&io_request_lock, flags);*/
+ spin_lock_irqsave(&io_request_lock, flags);
mesh_interrupt(irq, dev_id, ptregs);
- /*spin_unlock_irqrestore(&io_request_lock, flags);*/
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
static void handle_error(struct mesh_state *ms)
@@ -1643,6 +1643,7 @@ mesh_done(struct mesh_state *ms, int start_next)
static void
mesh_completed(struct mesh_state *ms, Scsi_Cmnd *cmd)
{
+#if 0
if (ms->completed_q == NULL)
ms->completed_q = cmd;
else
@@ -1651,6 +1652,9 @@ mesh_completed(struct mesh_state *ms, Scsi_Cmnd *cmd)
cmd->host_scribble = NULL;
queue_task(&ms->tqueue, &tq_immediate);
mark_bh(IMMEDIATE_BH);
+#else
+ (*cmd->scsi_done)(cmd);
+#endif
}
/*
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 474114991..45ae0eaf8 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -73,7 +73,7 @@
*/
/*
-** November 26 1998, version 3.1d
+** January 16 1998, version 3.1f
**
** Supported SCSI-II features:
** Synchronous negotiation
@@ -1017,7 +1017,7 @@ typedef struct {
#endif
/*
-** If the CPU and the NCR use same endian-ness adressing,
+** If the CPU and the NCR use same endian-ness addressing,
** no byte reordering is needed for script patching.
** Macro cpu_to_scr() is to be used for script patching.
** Macro scr_to_cpu() is to be used for getting a DWORD
@@ -1056,7 +1056,7 @@ typedef struct {
*/
/*
-** If the CPU and the NCR use same endian-ness adressing,
+** If the CPU and the NCR use same endian-ness addressing,
** no byte reordering is needed for accessing chip io
** registers. Functions suffixed by '_raw' are assumed
** to access the chip over the PCI without doing byte
@@ -6197,10 +6197,14 @@ void ncr_init (ncb_p np, int reset, char * msg, u_long code)
/*
** DEL 441 - 53C876 Rev 5 - Part Number 609-0392787/2788 - ITEM 2.
** Disable overlapped arbitration.
+ ** The 896 Rev 1 is also affected by this errata.
*/
if (np->device_id == PCI_DEVICE_ID_NCR_53C875 &&
np->revision_id >= 0x10 && np->revision_id <= 0x15)
OUTB (nc_ctest0, (1<<5));
+ else if (np->device_id == PCI_DEVICE_ID_NCR_53C896 &&
+ np->revision_id <= 0x1)
+ OUTB (nc_ccntl0, DPR);
/*
** Fill in target structure.
@@ -6829,7 +6833,7 @@ static void ncr_timeout (ncb_p np)
** scntl3: (see the manual)
**
** current script command:
-** dsp: script adress (relative to start of script).
+** dsp: script address (relative to start of script).
** dbc: first word of script command.
**
** First 16 register of the chip:
@@ -9683,7 +9687,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
(void) pcibios_read_config_dword(bus, device_fn,
PCI_BASE_ADDRESS_2, &base_2);
- /* Handle 64bit base adresses for 53C896. */
+ /* Handle 64bit base addresses for 53C896. */
if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
(void) pcibios_read_config_dword(bus, device_fn,
PCI_BASE_ADDRESS_3, &base_2);
@@ -9784,7 +9788,9 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
printk("succeeded.\n");
}
}
-
+
+
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,140)
if ( is_prep ) {
if (io_port >= 0x10000000) {
printk("ncr53c8xx: reallocating io_port (Wacky IBM)");
@@ -9802,6 +9808,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
pcibios_write_config_dword(bus, device_fn, PCI_BASE_ADDRESS_2, base_2);
}
}
+#endif
#endif /* __powerpc__ */
#ifdef __sparc__
@@ -9832,7 +9839,8 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
}
if ((chip->features & FE_CLSE) && !cache_line_size) {
- cache_line_size = CACHE_LINE_SIZE;
+ /* PCI_CACHE_LINE_SIZE value is in 32-bit words. */
+ cache_line_size = 64 / sizeof(u_int32);
if (initverbose >= 2)
printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
pcibios_write_config_byte(bus, device_fn,
@@ -9842,7 +9850,7 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
}
if (!latency_timer) {
- latency_timer = 248;
+ latency_timer = 128;
if (initverbose >= 2)
printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
pcibios_write_config_byte(bus, device_fn,
@@ -10194,8 +10202,6 @@ printk("ncr53c8xx_queue_command\n");
cmd->scsi_done = done;
cmd->host_scribble = NULL;
- cmd->SCp.ptr = NULL;
- cmd->SCp.buffer = NULL;
NCR_LOCK_NCB(np, flags);
@@ -10432,13 +10438,12 @@ static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd)
static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd)
{
- Scsi_Cmnd *wcmd;
+ Scsi_Cmnd **pcmd = &np->waiting_list;
- if (!(wcmd = np->waiting_list)) return 0;
- while (wcmd->next_wcmd) {
- if (cmd == (Scsi_Cmnd *) wcmd->next_wcmd) {
+ while (*pcmd) {
+ if (cmd == *pcmd) {
if (to_remove) {
- wcmd->next_wcmd = cmd->next_wcmd;
+ *pcmd = (Scsi_Cmnd *) cmd->next_wcmd;
cmd->next_wcmd = 0;
}
#ifdef DEBUG_WAITING_LIST
@@ -10446,6 +10451,7 @@ static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd
#endif
return cmd;
}
+ pcmd = (Scsi_Cmnd **) &(*pcmd)->next_wcmd;
}
return 0;
}
diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h
index 0139d2c5c..72b7ad4da 100644
--- a/drivers/scsi/ncr53c8xx.h
+++ b/drivers/scsi/ncr53c8xx.h
@@ -45,7 +45,7 @@
/*
** Name and revision of the driver
*/
-#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1d"
+#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - revision 3.1f"
/*
** Check supported Linux versions
@@ -347,7 +347,7 @@ int ncr53c8xx_release(struct Scsi_Host *);
#endif
#ifdef SCSI_NCR_BIG_ENDIAN
-#error "The NCR in BIG ENDIAN adressing mode is not (yet) supported"
+#error "The NCR in BIG ENDIAN addressing mode is not (yet) supported"
#endif
/*
@@ -769,7 +769,20 @@ struct ncr_reg {
/*53*/ u_char nc_53_;
/*54*/ u_short nc_sodl; /* Lowlevel: data out to scsi data */
-/*56*/ u_short nc_56_;
+/*56*/ u_char nc_ccntl0; /* Chip Control 0 (896) */
+ #define ENPMJ 0x80 /* Enable Phase Mismatch Jump */
+ #define PMJCTL 0x40 /* Phase Mismatch Jump Control */
+ #define ENNDJ 0x20 /* Enable Non Data PM Jump */
+ #define DISFC 0x10 /* Disable Auto FIFO Clear */
+ #define DILS 0x02 /* Disable Internal Load/Store */
+ #define DPR 0x01 /* Disable Pipe Req */
+
+/*57*/ u_char nc_ccntl1; /* Chip Control 1 (896) */
+ #define ZMOD 0x80 /* High Impedance Mode */
+ #define DDAC 0x08 /* Disable Dual Address Cycle */
+ #define XTIMOD 0x04 /* 64-bit Table Ind. Indexing Mode */
+ #define EXTIBMV 0x02 /* Enable 64-bit Table Ind. BMOV */
+ #define EXDBMV 0x01 /* Enable 64-bit Direct BMOV */
/*58*/ u_short nc_sbdl; /* Lowlevel: data from scsi data */
/*5a*/ u_short nc_5a_;
/*5c*/ u_char nc_scr0; /* Working register B */
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 75ab70e59..de54daef6 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -7,8 +7,7 @@
* under the terms of the GNU Public License.
*
* Current Maintainer: David Campbell (Perth, Western Australia, GMT+0800)
- * campbell@gear.torque.net
- * dcampbel@p01.as17.honeywell.com.au
+ * campbell@torque.net
*/
#include <linux/config.h>
@@ -68,7 +67,6 @@ void ppa_wakeup(void *ref)
printk("ppa: bug in ppa_wakeup\n");
return;
}
-
ppa_dev->p_busy = 0;
ppa_dev->base = ppa_dev->dev->port->base;
if (ppa_dev->cur_cmd)
@@ -91,7 +89,6 @@ static int ppa_pb_claim(int host_no)
ppa_hosts[host_no].p_busy = 1;
return 1;
}
-
if (ppa_hosts[host_no].cur_cmd)
ppa_hosts[host_no].cur_cmd->SCp.phase++;
return 0;
@@ -133,30 +130,26 @@ int ppa_detect(Scsi_Host_Template * host)
ppa_hosts[i].dev =
parport_register_device(pb, "ppa", NULL, ppa_wakeup,
- NULL, 0, (void *) &ppa_hosts[i]);
+ NULL, 0, (void *) &ppa_hosts[i]);
if (!ppa_hosts[i].dev)
- continue;
+ continue;
/* Claim the bus so it remembers what we do to the control
* registers. [ CTR and ECP ]
*/
- if (ppa_pb_claim(i))
- {
+ if (ppa_pb_claim(i)) {
unsigned long now = jiffies;
- while (ppa_hosts[i].p_busy)
- {
+ while (ppa_hosts[i].p_busy) {
schedule(); /* We are safe to schedule here */
- if (jiffies > now + 3*HZ)
- {
+ if (time_after(jiffies, now + 3 * HZ)) {
printk(KERN_ERR "ppa%d: failed to claim parport because a "
- "pardevice is owning the port for too longtime!\n",
+ "pardevice is owning the port for too longtime!\n",
i);
return 0;
}
}
}
-
ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
w_ctr(ppb, 0x0c);
modes = ppa_hosts[i].dev->port->modes;
@@ -211,8 +204,15 @@ int ppa_detect(Scsi_Host_Template * host)
nhosts++;
}
if (nhosts == 0) {
- if (try_again == 1)
+ if (try_again == 1) {
+ printk("WARNING - no ppa compatible devices found.\n");
+ printk(" As of 31/Aug/1998 Iomega started shipping parallel\n");
+ printk(" port ZIP drives with a different interface which is\n");
+ printk(" supported by the imm (ZIP Plus) driver. If the\n");
+ printk(" cable is marked with \"AutoDetect\", this is what has\n");
+ printk(" happened.\n");
return 0;
+ }
try_again = 1;
goto retry_entry;
} else
@@ -227,21 +227,11 @@ int ppa_detect(Scsi_Host_Template * host)
* Also gives a method to use a script to obtain optimum timings (TODO)
*/
-static inline int ppa_strncmp(const char *a, const char *b, int len)
-{
- int loop;
- for (loop = 0; loop < len; loop++)
- if (a[loop] != b[loop])
- return 1;
-
- return 0;
-}
-
static inline int ppa_proc_write(int hostno, char *buffer, int length)
{
unsigned long x;
- if ((length > 5) && (ppa_strncmp(buffer, "mode=", 5) == 0)) {
+ if ((length > 5) && (strncmp(buffer, "mode=", 5) == 0)) {
x = simple_strtoul(buffer + 5, NULL, 0);
ppa_hosts[hostno].mode = x;
return length;
@@ -326,7 +316,7 @@ static unsigned char ppa_wait(int host_no)
if (k)
return (r & 0xf0);
- /* Counter expired - Time out occured */
+ /* Counter expired - Time out occurred */
ppa_fail(host_no, DID_TIME_OUT);
printk("ppa timeout in ppa_wait\n");
return 0; /* command timed out */
@@ -360,227 +350,42 @@ static inline void ecp_sync(unsigned short ppb)
printk("ppa: ECP sync failed as data still present in FIFO.\n");
}
-/*
- * Here is the asm code for the SPP/PS2 protocols for the i386.
- * This has been optimised for speed on 386/486 machines. There will
- * be very little improvement on the current 586+ machines as it is the
- * IO statements which will limit throughput.
- */
-#ifdef __i386__
-#define BYTE_OUT(reg) \
- " movb " #reg ",%%al\n" \
- " outb %%al,(%%dx)\n" \
- " addl $2,%%edx\n" \
- " movb $0x0e,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " movb $0x0c,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " subl $2,%%edx\n"
-
-static inline int ppa_byte_out(unsigned short base, char *buffer, unsigned int len)
-{
- /*
- * %eax scratch
- * %ebx Data to transfer
- * %ecx Counter (Don't touch!!)
- * %edx Port
- * %esi Source buffer (mem pointer)
- *
- * In case you are wondering what the last line of the asm does...
- * <output allocation> : <input allocation> : <trashed registers>
- */
- asm("shr $2,%%ecx\n" \
- " jz .no_more_bulk_bo\n" \
- " .align 4\n" \
- ".loop_bulk_bo:\n" \
- " movl (%%esi),%%ebx\n" \
- BYTE_OUT(%%bl) \
- BYTE_OUT(%%bh) \
- " rorl $16,%%ebx\n" \
- BYTE_OUT(%%bl) \
- BYTE_OUT(%%bh) \
- " addl $4,%%esi\n" \
- " loop .loop_bulk_bo\n" \
- " .align 4\n" \
- ".no_more_bulk_bo:" \
- : "=S"(buffer): "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
-
- asm("andl $3,%%ecx\n" \
- " jz .no_more_loose_bo\n" \
- " .align 4\n" \
- ".loop_loose_bo:\n" \
- BYTE_OUT((%%esi)) \
- " incl %%esi\n" \
- " loop .loop_loose_bo\n" \
- ".no_more_loose_bo:\n" \
- : /* no output */ : "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
- return 1; /* All went well - we hope! */
-}
-
-#define BYTE_IN(reg) \
- " inb (%%dx),%%al\n" \
- " movb %%al," #reg "\n" \
- " addl $2,%%edx\n" \
- " movb $0x27,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " movb $0x25,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " subl $2,%%edx\n"
-
-static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
-{
- /*
- * %eax scratch
- * %ebx Data to transfer
- * %ecx Counter (Don't touch!!)
- * %edx Port
- * %esi Source buffer (mem pointer)
- *
- * In case you are wondering what the last line of the asm does...
- * <output allocation> : <input allocation> : <trashed registers>
- */
- asm("shr $2,%%ecx\n" \
- " jz .no_more_bulk_bi\n" \
- " .align 4\n" \
- ".loop_bulk_bi:\n" \
- BYTE_IN(%%bl) \
- BYTE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- BYTE_IN(%%bl) \
- BYTE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- " movl %%ebx,(%%esi)\n" \
- " addl $4,%%esi\n" \
- " loop .loop_bulk_bi\n" \
- " .align 4\n" \
- ".no_more_bulk_bi:" \
- : "=S"(buffer): "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
-
- asm("andl $3,%%ecx\n" \
- " jz .no_more_loose_bi\n" \
- " .align 4\n" \
- ".loop_loose_bi:\n" \
- BYTE_IN((%%esi)) \
- " incl %%esi\n" \
- " loop .loop_loose_bi\n" \
- ".no_more_loose_bi:\n" \
- : /* no output */ : "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
- return 1; /* All went well - we hope! */
-}
-
-#define NIBBLE_IN(reg) \
- " incl %%edx\n" \
- " movb $0x04,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " decl %%edx\n" \
- " inb (%%dx),%%al\n" \
- " andb $0xf0,%%al\n" \
- " movb %%al," #reg "\n" \
- " incl %%edx\n" \
- " movb $0x06,%%al\n" \
- " outb %%al,(%%dx)\n" \
- " decl %%edx\n" \
- " inb (%%dx),%%al\n" \
- " shrb $4,%%al\n" \
- " orb %%al," #reg "\n"
-
-static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
-{
- /*
- * %eax scratch
- * %ebx Data to transfer
- * %ecx Counter (Don't touch!!)
- * %edx Port
- * %esi Source buffer (mem pointer)
- *
- * In case you are wondering what the last line of the asm does...
- * <output allocation> : <input allocation> : <trashed registers>
- */
- asm("shr $2,%%ecx\n" \
- " jz .no_more_bulk_ni\n" \
- " .align 4\n" \
- ".loop_bulk_ni:\n" \
- NIBBLE_IN(%%bl) \
- NIBBLE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- NIBBLE_IN(%%bl) \
- NIBBLE_IN(%%bh) \
- " rorl $16,%%ebx\n" \
- " movl %%ebx,(%%esi)\n" \
- " addl $4,%%esi\n" \
- " loop .loop_bulk_ni\n" \
- " .align 4\n" \
- ".no_more_bulk_ni:" \
- : "=S"(buffer): "c"(len), "d"(str_p), "S"(buffer):"eax", "ebx", "ecx");
-
- asm("andl $3,%%ecx\n" \
- " jz .no_more_loose_ni\n" \
- " .align 4\n" \
- ".loop_loose_ni:\n" \
- NIBBLE_IN((%%esi)) \
- " incl %%esi\n" \
- " loop .loop_loose_ni\n" \
- ".no_more_loose_ni:\n" \
- : /* no output */ : "c"(len), "d"(str_p), "S"(buffer):"eax", "ebx", "ecx");
- return 1; /* All went well - we hope! */
-}
-#else /* Old style C routines */
-
-static inline int ppa_byte_out(unsigned short base, const char *buffer, int len)
+static int ppa_byte_out(unsigned short base, const char *buffer, int len)
{
- unsigned short ctr_p = base + 2;
int i;
for (i = len; i; i--) {
- outb(*buffer++, base);
- outb(0xe, ctr_p);
- outb(0xc, ctr_p);
+ w_dtr(base, *buffer++);
+ w_ctr(base, 0xe);
+ w_ctr(base, 0xc);
}
return 1; /* All went well - we hope! */
}
-static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
+static int ppa_byte_in(unsigned short base, char *buffer, int len)
{
- unsigned short ctr_p = base + 2;
int i;
for (i = len; i; i--) {
- *buffer++ = inb(base);
- outb(0x27, ctr_p);
- outb(0x25, ctr_p);
+ *buffer++ = r_dtr(base);
+ w_ctr(base, 0x27);
+ w_ctr(base, 0x25);
}
return 1; /* All went well - we hope! */
}
-static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
+static int ppa_nibble_in(unsigned short base, char *buffer, int len)
{
- unsigned short ctr_p = str_p + 1;
- unsigned char h, l;
- int i;
+ for (; len; len--) {
+ unsigned char h;
- for (i = len; i; i--) {
- outb(0x4, ctr_p);
- h = inb(str_p);
- outb(0x6, ctr_p);
- l = inb(str_p);
- *buffer++ = (h & 0xf0) | ((l & 0xf0) >> 4);
+ w_ctr(base, 0x4);
+ h = r_str(base) & 0xf0;
+ w_ctr(base, 0x6);
+ *buffer++ = h | ((r_str(base) & 0xf0) >> 4);
}
return 1; /* All went well - we hope! */
}
-#endif
-
-static inline int ppa_epp_out(unsigned short epp_p, unsigned short str_p, const char *buffer, int len)
-{
- int i;
- for (i = len; i; i--) {
- outb(*buffer++, epp_p);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- if (inb(str_p) & 0x01)
- return 0;
-#endif
- }
- return 1;
-}
static int ppa_out(int host_no, char *buffer, int len)
{
@@ -605,16 +410,17 @@ static int ppa_out(int host_no, char *buffer, int len)
case PPA_EPP_8:
epp_reset(ppb);
w_ctr(ppb, 0x4);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- r = ppa_epp_out(ppb + 4, ppb + 1, buffer, len);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ outsw(ppb + 4, buffer, len >> 1);
#else
if (!(((long) buffer | len) & 0x03))
outsl(ppb + 4, buffer, len >> 2);
+#endif
else
outsb(ppb + 4, buffer, len);
w_ctr(ppb, 0xc);
r = !(r_str(ppb) & 0x01);
-#endif
w_ctr(ppb, 0xc);
ecp_sync(ppb);
break;
@@ -626,19 +432,6 @@ static int ppa_out(int host_no, char *buffer, int len)
return r;
}
-static inline int ppa_epp_in(int epp_p, int str_p, char *buffer, int len)
-{
- int i;
- for (i = len; i; i--) {
- *buffer++ = inb(epp_p);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- if (inb(str_p) & 0x01)
- return 0;
-#endif
- }
- return 1;
-}
-
static int ppa_in(int host_no, char *buffer, int len)
{
int r;
@@ -653,7 +446,7 @@ static int ppa_in(int host_no, char *buffer, int len)
switch (ppa_hosts[host_no].mode) {
case PPA_NIBBLE:
/* 4 bit input, with a loop */
- r = ppa_nibble_in(ppb + 1, buffer, len);
+ r = ppa_nibble_in(ppb, buffer, len);
w_ctr(ppb, 0xc);
break;
@@ -670,16 +463,17 @@ static int ppa_in(int host_no, char *buffer, int len)
case PPA_EPP_8:
epp_reset(ppb);
w_ctr(ppb, 0x24);
-#ifdef CONFIG_SCSI_PPA_HAVE_PEDANTIC
- r = ppa_epp_in(ppb + 4, ppb + 1, buffer, len);
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ if (!(((long) buffer | len) & 0x01))
+ insw(ppb + 4, buffer, len >> 1);
#else
if (!(((long) buffer | len) & 0x03))
insl(ppb + 4, buffer, len >> 2);
+#endif
else
insb(ppb + 4, buffer, len);
w_ctr(ppb, 0x2c);
r = !(r_str(ppb) & 0x01);
-#endif
w_ctr(ppb, 0x2c);
ecp_sync(ppb);
break;
@@ -867,7 +661,7 @@ static int ppa_completion(Scsi_Cmnd * cmd)
* If we have been running for more than a full timer tick
* then take a rest.
*/
- if (jiffies > start_jiffies + 1)
+ if (time_after(jiffies, start_jiffies + 1))
return 0;
if (((r & 0xc0) != 0xc0) || (cmd->SCp.this_residual <= 0)) {
@@ -1010,7 +804,7 @@ static int ppa_engine(ppa_struct * tmp, Scsi_Cmnd * cmd)
unsigned char l = 0, h = 0;
int retv;
- /* First check for any errors that may of occured
+ /* First check for any errors that may of occurred
* Here we check for internal errors
*/
if (tmp->failed)
@@ -1041,8 +835,7 @@ static int ppa_engine(ppa_struct * tmp, Scsi_Cmnd * cmd)
if ((r_str(ppb) & 0x08) == 0x00)
retv--;
- if (retv)
- {
+ if (retv) {
if ((jiffies - tmp->jstart) > (1 * HZ)) {
printk("ppa: Parallel port cable is unplugged!!\n");
ppa_fail(host_no, DID_BUS_BUSY);
diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
index c58dd39b2..b3beb9f5d 100644
--- a/drivers/scsi/ppa.h
+++ b/drivers/scsi/ppa.h
@@ -2,15 +2,15 @@
* the Iomega ZIP drive
*
* (c) 1996 Grant R. Guenther grant@torque.net
- * David Campbell campbell@torque.net
+ * David Campbell campbell@torque.net
*
- * All comments to David.
+ * All comments to David.
*/
#ifndef _PPA_H
#define _PPA_H
-#define PPA_VERSION "2.01"
+#define PPA_VERSION "2.03 (for Linux 2.0.0)"
/*
* this driver has been hacked by Matteo Frigo (athena@theory.lcs.mit.edu)
@@ -26,25 +26,36 @@
*
* Corrected ppa.h for 2.1.x kernels (>=2.1.85)
* Modified "Nat Semi Kludge" for extended chipsets
- * [1.41]
+ * [1.41]
*
* Fixed id_probe for EPP 1.9 chipsets (misdetected as EPP 1.7)
- * [1.42]
+ * [1.42]
*
* Development solely for 2.1.x kernels from now on!
- * [2.00]
+ * [2.00]
*
* Hack and slash at the init code (EPP device check routine)
* Added INSANE option.
- * [2.01]
+ * [2.01]
*
* Patch applied to sync against the 2.1.x kernel code
* Included qboot_zip.sh
- * [2.02]
+ * [2.02]
+ *
+ * Cleaned up the mess left by someone else trying to fix the
+ * asm section to keep egcc happy. The asm section no longer
+ * exists, the nibble code is *almost* as fast as the asm code
+ * providing it is compiled with egcc.
+ *
+ * Other clean ups include the follow changes:
+ * CONFIG_SCSI_PPA_HAVE_PEDANTIC => CONFIG_SCSI_IZIP_EPP16
+ * added CONFIG_SCSI_IZIP_SLOW_CTR option
+ * [2.03]
*/
/* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
#ifdef PPA_CODE
+#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -80,7 +91,11 @@ static char *PPA_MODE_STRING[] =
"PS/2",
"EPP 8 bit",
"EPP 16 bit",
+#ifdef CONFIG_SCSI_IZIP_EPP16
+ "EPP 16 bit",
+#else
"EPP 32 bit",
+#endif
"Unknown"};
/* This is a global option */
@@ -98,23 +113,6 @@ int ppa_sg = SG_ALL; /* enable/disable scatter-gather. */
#define CONNECT_EPP_MAYBE 1
#define CONNECT_NORMAL 0
-/* INSANE code */
-#define PPA_INSANE 0
-#if PPA_INSANE > 0
-#define r_dtr(x) (unsigned char)inb_p((x))
-#define r_str(x) (unsigned char)inb_p((x)+1)
-#define r_ctr(x) (unsigned char)inb_p((x)+2)
-#define r_epp(x) (unsigned char)inb_p((x)+4)
-#define r_fifo(x) (unsigned char)inb_p((x)+0x400)
-#define r_ecr(x) (unsigned char)inb_p((x)+0x402)
-
-#define w_dtr(x,y) outb_p(y, (x))
-#define w_str(x,y) outb_p(y, (x)+1)
-#define w_ctr(x,y) outb_p(y, (x)+2)
-#define w_epp(x,y) outb_p(y, (x)+4)
-#define w_fifo(x,y) outb_p(y, (x)+0x400)
-#define w_ecr(x,y) outb_p(y, (x)+0x402)
-#else /* PPA_INSANE */
#define r_dtr(x) (unsigned char)inb((x))
#define r_str(x) (unsigned char)inb((x)+1)
#define r_ctr(x) (unsigned char)inb((x)+2)
@@ -124,11 +122,15 @@ int ppa_sg = SG_ALL; /* enable/disable scatter-gather. */
#define w_dtr(x,y) outb(y, (x))
#define w_str(x,y) outb(y, (x)+1)
-#define w_ctr(x,y) outb(y, (x)+2)
#define w_epp(x,y) outb(y, (x)+4)
#define w_fifo(x,y) outb(y, (x)+0x400)
#define w_ecr(x,y) outb(y, (x)+0x402)
-#endif /* PPA_INSANE */
+
+#ifdef CONFIG_SCSI_IZIP_SLOW_CTR
+#define w_ctr(x,y) outb_p(y, (x)+2)
+#else
+#define w_ctr(x,y) outb(y, (x)+2)
+#endif
static int ppa_engine(ppa_struct *, Scsi_Cmnd *);
static int ppa_in(int, char *, int);
@@ -154,7 +156,7 @@ int ppa_biosparam(Disk *, kdev_t, int *);
#define PPA { proc_dir: &proc_scsi_ppa, \
proc_info: ppa_proc_info, \
- name: "Iomega parport ZIP drive",\
+ name: "Iomega VPI0 (ppa) interface",\
detect: ppa_detect, \
release: ppa_release, \
command: ppa_command, \
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 20fd1a58c..84638f786 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -30,6 +30,8 @@
* Leonard N. Zubkoff <lnz@dandelion.com>
*
* Converted cli() code to spinlocks, Ingo Molnar
+ *
+ * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
*/
#include <linux/config.h>
@@ -277,6 +279,9 @@ static struct dev_info device_list[] =
{"MATSHITA","PD","*", BLIST_FORCELUN | BLIST_SINGLELUN},
{"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 */
+{"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN},
+{"IBM","DPES-","*", BLIST_NOTQ | BLIST_NOLUN},
+{"WDIGTL","WDE","*", BLIST_NOTQ | BLIST_NOLUN},
/*
* Must be at end of list...
*/
@@ -525,9 +530,18 @@ static void scan_scsis (struct Scsi_Host *shpnt,
}
else {
+ /* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0 */
+ int order_dev;
+
for (channel = 0; channel <= shpnt->max_channel; channel++) {
for (dev = 0; dev < shpnt->max_id; ++dev) {
- if (shpnt->this_id != dev) {
+ if( shpnt->reverse_ordering)
+ /* Shift to scanning 15,14,13... or 7,6,5,4, */
+ order_dev = shpnt->max_id-dev-1;
+ else
+ order_dev = dev;
+
+ if (shpnt->this_id != order_dev) {
/*
* We need the for so our continue, etc. work fine. We put this in
@@ -538,7 +552,7 @@ static void scan_scsis (struct Scsi_Host *shpnt,
max_scsi_luns : shpnt->max_lun);
sparse_lun = 0;
for (lun = 0; lun < max_dev_lun; ++lun) {
- if (!scan_scsis_single (channel, dev, lun, &max_dev_lun,
+ if (!scan_scsis_single (channel, order_dev, lun, &max_dev_lun,
&sparse_lun, &SDpnt, SCpnt, shpnt,
scsi_result)
&& !sparse_lun)
@@ -1301,7 +1315,7 @@ inline int internal_cmnd (Scsi_Cmnd * SCpnt)
*/
timeout = host->last_reset + MIN_RESET_DELAY;
- if (jiffies < timeout) {
+ if (host->resetting && time_before(jiffies, timeout)) {
int ticks_remaining = timeout - jiffies;
/*
* NOTE: This may be executed from within an interrupt
@@ -1314,7 +1328,7 @@ inline int internal_cmnd (Scsi_Cmnd * SCpnt)
*/
spin_unlock_irq(&io_request_lock);
while (--ticks_remaining >= 0) mdelay(1+999/HZ);
- host->last_reset = jiffies - MIN_RESET_DELAY;
+ host->resetting = 0;
spin_lock_irq(&io_request_lock);
}
@@ -1371,7 +1385,7 @@ inline int internal_cmnd (Scsi_Cmnd * SCpnt)
#ifdef DEBUG_DELAY
clock = jiffies + 4 * HZ;
spin_unlock_irq(&io_request_lock);
- while (jiffies < clock) barrier();
+ while (time_before(jiffies, clock)) barrier();
spin_lock_irq(&io_request_lock);
printk("done(host = %d, result = %04x) : routine at %p\n",
host->host_no, temp, host->hostt->command);
@@ -1739,7 +1753,7 @@ scsi_finish_command(Scsi_Cmnd * SCpnt)
host_active = NULL;
/* For block devices "wake_up" is done in end_scsi_request */
- if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
+ if (!SCSI_BLK_MAJOR(MAJOR(SCpnt->request.rq_dev))) {
struct Scsi_Host * next;
for (next = host->block; next != host; next = next->block)
@@ -2747,7 +2761,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt)
{
if(SDpnt->host->hostt == tpnt
&& SDpnt->host->hostt->module
- && SDpnt->host->hostt->module->usecount) return;
+ && GET_USE_COUNT(SDpnt->host->hostt->module)) return;
/*
* FIXME(eric) - We need to find a way to notify the
* low level driver that we are shutting down - via the
@@ -3036,7 +3050,7 @@ static int scsi_unregister_device(struct Scsi_Device_Template * tpnt)
/*
* If we are busy, this is not going to fly.
*/
- if(tpnt->module->usecount != 0) return 0;
+ if(GET_USE_COUNT(tpnt->module) != 0) return 0;
/*
* Next, detach the devices from the driver.
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 2539774c6..046e13b24 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -317,9 +317,9 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#define IS_RESETTING 0x08
#define IS_ABORTING 0x10
#define ASKED_FOR_SENSE 0x20
+#define SYNC_RESET 0x40
-
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
#include <asm/pgtable.h>
#define CONTIGUOUS_BUFFERS(X,Y) \
(virt_to_phys((X)->b_data+(X)->b_size-1)+1==virt_to_phys((Y)->b_data))
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 281c9ce28..8536f69b4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -518,10 +518,10 @@ int scsi_debug_command(Scsi_Cmnd * SCpnt)
static void scsi_debug_intr_handle(unsigned long indx)
{
Scsi_Cmnd * SCtmp;
- int pending;
void (*my_done)(Scsi_Cmnd *);
- unsigned long flags;
+#ifdef DEBUG
int to;
+#endif
#if 0
del_timer(&timeout[indx]);
@@ -565,9 +565,11 @@ int scsi_debug_detect(Scsi_Host_Template * tpnt)
int scsi_debug_abort(Scsi_Cmnd * SCpnt)
{
+#if 0
int j;
void (*my_done)(Scsi_Cmnd *);
unsigned long flags;
+#endif
DEB(printk("scsi_debug_abort\n"));
#if 0
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 057963ca6..a3d7c3538 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -142,7 +142,6 @@ scsi_delete_timer(Scsi_Cmnd * SCset)
SCSI_LOG_ERROR_RECOVERY(5,printk("Clearing timer for command %p\n", SCset));
SCset->eh_timeout.data = (unsigned long) NULL;
- SCset->eh_timeout.expires = 0;
SCset->eh_timeout.function = NULL;
return rtn;
@@ -970,7 +969,7 @@ int scsi_decide_disposition (Scsi_Cmnd * SCpnt)
/*
* Note - this means that we just report the status back to the
* top level driver, not that we actually think that it indicates
- * sucess.
+ * success.
*/
return SUCCESS;
/*
@@ -1183,14 +1182,14 @@ STATIC int scsi_check_sense (Scsi_Cmnd * SCpnt)
}
if (SCpnt->sense_buffer[2] & 0xe0)
- return FAILED;
+ return SUCCESS;
switch (SCpnt->sense_buffer[2] & 0xf)
{
case NO_SENSE:
return SUCCESS;
case RECOVERED_ERROR:
- return SOFT_ERROR;
+ return /* SOFT_ERROR */ SUCCESS;
case ABORTED_COMMAND:
return NEEDS_RETRY;
@@ -1213,18 +1212,17 @@ STATIC int scsi_check_sense (Scsi_Cmnd * SCpnt)
case COPY_ABORTED:
case VOLUME_OVERFLOW:
case MISCOMPARE:
+ return SUCCESS;
case MEDIUM_ERROR:
- return FAILED;
+ return NEEDS_RETRY;
case ILLEGAL_REQUEST:
- return SUCCESS;
-
case BLANK_CHECK:
case DATA_PROTECT:
case HARDWARE_ERROR:
default:
- return FAILED;
+ return SUCCESS;
}
}
diff --git a/drivers/scsi/scsi_obsolete.c b/drivers/scsi/scsi_obsolete.c
index 064785074..2ca49f71c 100644
--- a/drivers/scsi/scsi_obsolete.c
+++ b/drivers/scsi/scsi_obsolete.c
@@ -23,6 +23,9 @@
* Major improvements to the timeout, abort, and reset processing,
* as well as performance modifications for large queue depths by
* Leonard N. Zubkoff <lnz@dandelion.com>
+ *
+ * Improved compatibility with 2.0 behaviour by Manfred Spraul
+ * <masp0008@stud.uni-sb.de>
*/
/*
@@ -354,6 +357,18 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result);
#endif
+ if(SCpnt->flags & SYNC_RESET)
+ {
+ /*
+ * The behaviou of scsi_reset(SYNC) was changed in 2.1.? .
+ * The scsi mid-layer does a REDO after every sync reset, the driver
+ * must not do that any more. In order to prevent old drivers from
+ * crashing, all scsi_done() calls during sync resets are ignored.
+ */
+ printk("scsi%d: device driver called scsi_done() "
+ "for a syncronous reset.\n", SCpnt->host->host_no);
+ return;
+ }
if(SCpnt->flags & WAS_SENSE)
{
SCpnt->use_sg = SCpnt->old_use_sg;
@@ -494,7 +509,7 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
case RESERVATION_CONFLICT:
printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
" reset.\n", SCpnt->host->host_no, SCpnt->channel);
- scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
+ scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
status = REDO;
break;
default:
@@ -607,17 +622,14 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
if ((++SCpnt->retries) < SCpnt->allowed)
{
if ((SCpnt->retries >= (SCpnt->allowed >> 1))
- /* FIXME: last_reset == 0 is allowed */
- && time_after(jiffies, SCpnt->host->last_reset
- + MIN_RESET_PERIOD)
+ && !(SCpnt->host->resetting && time_before(jiffies, SCpnt->host->last_reset + MIN_RESET_PERIOD))
&& !(SCpnt->flags & WAS_RESET))
{
printk("scsi%d channel %d : resetting for second half of retries.\n",
SCpnt->host->host_no, SCpnt->channel);
scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
- break;
+ /* fall through to REDO */
}
-
}
else
{
@@ -659,7 +671,7 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
host_active = NULL;
/* For block devices "wake_up" is done in end_scsi_request */
- if (!SCSI_BLK_MAJOR(SCpnt->request.rq_dev)) {
+ if (!SCSI_BLK_MAJOR(MAJOR(SCpnt->request.rq_dev))) {
struct Scsi_Host * next;
for (next = host->block; next != host; next = next->block)
@@ -916,6 +928,8 @@ static int scsi_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
SCpnt->internal_timeout |= IN_RESET;
update_timeout(SCpnt, RESET_TIMEOUT);
+ if (reset_flags & SCSI_RESET_SYNCHRONOUS)
+ SCpnt->flags |= SYNC_RESET;
if (host->host_busy)
{
for(SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next)
@@ -935,6 +949,12 @@ static int scsi_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
}
host->last_reset = jiffies;
+ host->resetting = 1;
+ /*
+ * I suppose that the host reset callback will not play
+ * with the resetting field. We have just set the resetting
+ * flag here. -arca
+ */
temp = host->hostt->reset(SCpnt, reset_flags);
/*
This test allows the driver to introduce an additional bus
@@ -953,13 +973,21 @@ static int scsi_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
{
if (!host->block) host->host_busy++;
host->last_reset = jiffies;
- SCpnt->flags |= (WAS_RESET | IS_RESETTING);
+ host->resetting = 1;
+ SCpnt->flags |= (WAS_RESET | IS_RESETTING);
+ /*
+ * I suppose that the host reset callback will not play
+ * with the resetting field. We have just set the resetting
+ * flag here. -arca
+ */
temp = host->hostt->reset(SCpnt, reset_flags);
if (time_before(host->last_reset, jiffies) ||
(time_after(host->last_reset, jiffies + 20 * HZ)))
host->last_reset = jiffies;
if (!host->block) host->host_busy--;
}
+ if (reset_flags & SCSI_RESET_SYNCHRONOUS)
+ SCpnt->flags &= ~SYNC_RESET;
#ifdef DEBUG
printk("scsi reset function returned %d\n", temp);
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 4ed9ba634..459a245d5 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -307,6 +307,13 @@ void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len)
*size = y;
return;
}
+
+#else
+
+void proc_print_scsidevice(Scsi_Device *scd, char *buffer, int *size, int len)
+{
+}
+
#endif /* CONFIG_PROC_FS */
/*
diff --git a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c
index c6d83f8a2..e73335a24 100644
--- a/drivers/scsi/scsi_syms.c
+++ b/drivers/scsi/scsi_syms.c
@@ -72,9 +72,7 @@ EXPORT_SYMBOL(scsi_logging_level);
EXPORT_SYMBOL(scsi_sleep);
-#if defined(CONFIG_PROC_FS)
EXPORT_SYMBOL(proc_print_scsidevice);
-#endif
/*
* These are here only while I debug the rest of the scsi stuff.
*/
diff --git a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
index e09e7dc3b..14bf46435 100644
--- a/drivers/scsi/scsiiom.c
+++ b/drivers/scsi/scsiiom.c
@@ -4,7 +4,7 @@
* Description: Device Driver for Tekram DC-390 (T) PCI SCSI *
* Bus Master Host Adapter *
***********************************************************************/
-/* $Id: scsiiom.c,v 2.3 1998/10/24 09:10:28 garloff Exp $ */
+/* $Id: scsiiom.c,v 1.5 1999/01/04 16:07:12 ralf Exp $ */
UCHAR
dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
@@ -36,7 +36,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
DC390_write8 (ScsiFifo, bval);
bval1 = SEL_W_ATN;
pSRB->SRBState = SRB_START_;
- DEBUG1(printk ("DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
+ DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
if( pDCB->SyncMode & SYNC_ENABLE )
{
if( !(pDCB->IdentifyMsg & 7) || /* LUN == 0 || Cmd != INQUIRY */
@@ -53,21 +53,21 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
if(pDCB->SyncMode & EN_TAG_QUEUEING)
{
DC390_write8 (ScsiFifo, MSG_SIMPLE_QTAG);
- DEBUG1(printk ("DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);)
bval = 0; wlval = 1;
while (wlval & pDCB->TagMask)
{ bval++; wlval <<= 1; };
pDCB->TagMask |= wlval;
DC390_write8 (ScsiFifo, bval);
pSRB->TagNumber = bval;
- DEBUG1(printk ("DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
+ DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
bval1 = SEL_W_ATN3;
pSRB->SRBState = SRB_START_;
}
else /* No TagQ */
{
bval1 = SEL_W_ATN;
- DEBUG1(printk ("DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
pSRB->SRBState = SRB_START_;
}
}
@@ -82,7 +82,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
bval &= 0xBF; /* No DisConn */
DC390_write8 (ScsiFifo, bval);
bval1 = SEL_W_ATN;
- DEBUG1(printk ("DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
+ DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);)
pSRB->SRBState = SRB_START_;
/* ??? */
if( pDCB->SyncMode & SYNC_ENABLE )
@@ -101,13 +101,13 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
if(pDCB->SyncMode & EN_TAG_QUEUEING)
{
pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG;
- DEBUG1(printk ("DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);)
bval = 0; wlval = 1;
while (wlval & pDCB->TagMask)
{ bval++; wlval <<= 1; };
pDCB->TagMask |= wlval;
pSRB->TagNumber = bval;
- DEBUG1(printk ("DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
+ DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);)
pSRB->MsgOutBuf[1] = bval;
pSRB->MsgCnt = 2;
bval1 = SEL_W_ATN_STOP;
@@ -119,7 +119,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
pSRB->MsgCnt = 1;
pSRB->SRBState = SRB_START_;
bval1 = SEL_W_ATN_STOP;
- DEBUG1(printk ("DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
+ DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);)
};
}
}
@@ -134,7 +134,7 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
DC390_write8 (ScsiFifo, bval);
DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer));
DC390_write8 (ScsiFifo, bval);
- DEBUG1(printk ("DC390: AutoReqSense !\n");)
+ DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");)
}
else /* write cmnd to bus */
{
@@ -150,16 +150,16 @@ dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB )
{
pSRB->SRBState = SRB_READY;
pDCB->TagMask &= ~( 1 << pSRB->TagNumber );
- DEBUG0(printk ("DC390: Interrupt during StartSCSI!\n");)
+ DEBUG0(printk (KERN_WARNING "DC390: Interrupt during StartSCSI!\n");)
return 1;
}
else
{
pSRB->ScsiPhase = SCSI_NOP1;
DEBUG0(if (pACB->pActiveDCB) \
- printk ("DC390: ActiveDCB != 0\n");)
+ printk (KERN_WARNING "DC390: ActiveDCB != 0\n");)
DEBUG0(if (pDCB->pActiveSRB) \
- printk ("DC390: ActiveSRB != 0\n");)
+ printk (KERN_WARNING "DC390: ActiveSRB != 0\n");)
pACB->pActiveDCB = pDCB;
pDCB->pActiveSRB = pSRB;
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
@@ -183,12 +183,10 @@ dc390_dma_intr (PACB pACB)
DEBUG0(PDEVSET1;)
DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate);)
DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
- { printk("DC390: PCI state = %04x!\n", pstate); \
+ { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));};)
- dstate = DC390_read8 (DMA_Status);
- DC390_write8 (DMA_Status, dstate); /* clear */
- //DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
+ dstate = DC390_read8 (DMA_Status);
if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
else pSRB = pACB->pActiveDCB->pActiveSRB;
@@ -207,12 +205,11 @@ dc390_dma_intr (PACB pACB)
{
DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n");)
dstate = DC390_read8 (DMA_Status);
- DC390_write8 (DMA_Status, dstate); /* clear */
residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
DC390_read8 (CtcReg_High) << 16;
residual += DC390_read8 (Current_Fifo) & 0x1f;
} while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
- if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr));
+ if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
/* residual = ... */
}
else
@@ -231,6 +228,7 @@ dc390_dma_intr (PACB pACB)
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
}
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
return dstate;
};
#endif
@@ -245,14 +243,16 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
UCHAR phase, i;
void (*stateV)( PACB, PSRB, PUCHAR );
UCHAR istate, istatus;
+#if DMA_INT
UCHAR dstatus;
+#endif
DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS
pACB = dc390_pACB_start;
if (pACB == 0)
{
- printk(KERN_ERR "DC390: Interrupt on uninitialized adapter!\n");
+ printk(KERN_WARNING "DC390: Interrupt on uninitialized adapter!\n");
return;
}
DC390_LOCK_DRV;
@@ -275,8 +275,8 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);)
- if( pACB == (PACB )-1) { DC390_UNLOCK_DRV; return; };
-
+ if( !pACB ) { DC390_UNLOCK_DRV; return; };
+
#if DMA_INT
DC390_LOCK_IO;
DC390_LOCK_ACB;
@@ -284,15 +284,17 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
DC390_UNLOCK_ACB;
DC390_UNLOCK_IO;
- DEBUG1(printk ("dstatus=%02x,", dstatus);)
+ DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus);)
if (! (dstatus & SCSI_INTERRUPT))
{
- DEBUG0(printk ("DC390 Int w/o SCSI actions (only DMA?)\n");)
+ DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");)
DC390_UNLOCK_DRV;
return;
};
#else
- dstatus = DC390_read8 (DMA_Status);
+ //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
+ //dstatus = DC390_read8 (DMA_Status);
+ //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
#endif
DC390_LOCK_IO;
@@ -302,14 +304,15 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
istate = DC390_read8 (Intern_State);
istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
- DEBUG1(printk ("Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);)
- dc390_laststatus = dstatus<<24 | sstatus<<16 | istate<<8 | istatus;
+ DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);)
+ dc390_laststatus &= ~0x00ffffff;
+ dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
if (sstatus & ILLEGAL_OP_ERR)
- {
- printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus);
- dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
- };
+ {
+ printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus);
+ dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
+ };
if(istatus & DISCONNECTED)
{
@@ -323,18 +326,6 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
goto unlock;
}
- if(istatus & INVALID_CMD)
- {
- dc390_InvalidCmd( pACB );
- goto unlock;
- }
-
- if(istatus & SCSI_RESET)
- {
- dc390_ScsiRstDetect( pACB );
- goto unlock;
- }
-
if( istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) )
{
pDCB = pACB->pActiveDCB;
@@ -345,7 +336,7 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
};
pSRB = pDCB->pActiveSRB;
if( pDCB->DCBFlag & ABORT_DEV_ )
- dc390_EnableMsgOut( pACB, pSRB );
+ dc390_EnableMsgOut_Abort (pACB, pSRB);
phase = pSRB->ScsiPhase;
DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus);)
@@ -357,7 +348,21 @@ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus);)
stateV = (void *) dc390_phase1[phase];
( *stateV )( pACB, pSRB, &sstatus );
+ goto unlock;
}
+
+ if(istatus & INVALID_CMD)
+ {
+ dc390_InvalidCmd( pACB );
+ goto unlock;
+ }
+
+ if(istatus & SCSI_RESET)
+ {
+ dc390_ScsiRstDetect( pACB );
+ goto unlock;
+ }
+
unlock:
DC390_LOCK_DRV_NI;
DC390_UNLOCK_ACB;
@@ -380,6 +385,7 @@ dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
UCHAR sstatus;
PSGL psgl;
ULONG ResidCnt, xferCnt;
+ UCHAR dstate = 0;
sstatus = *psstatus;
@@ -391,10 +397,9 @@ dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
if( sstatus & COUNT_2_ZERO )
{
int ctr = 5000000; /* only try for about a tenth of a second */
- while( --ctr && !(DC390_read8 (DMA_Status) & DMA_XFER_DONE) && pSRB->SGToBeXferLen )
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
- if (!ctr) printk (KERN_CRIT "DC390: DataOut_0: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr));
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
+ while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
+ if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
pSRB->SGIndex++;
if( pSRB->SGIndex < pSRB->SGcount )
@@ -443,15 +448,14 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
{
int ctr = 5000000; /* only try for about a tenth of a second */
int dstate = 0;
- while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen )
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
- if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr));
+ while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen );
+ if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \
+ ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \
+ ((ULONG) DC390_read8 (CtcReg_Low));)
- DEBUG1(printk ("Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);)
- DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
+ DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);)
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
@@ -474,7 +478,7 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
bval = DC390_read8 (Current_Fifo);
while( bval & 0x1f )
{
- DEBUG1(printk ("Check for residuals,");)
+ DEBUG1(printk (KERN_DEBUG "Check for residuals,");)
if( (bval & 0x1f) == 1 )
{
for(i=0; i < 0x100; i++)
@@ -494,17 +498,18 @@ dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
}
din_1:
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
- for (i=0; i<0x8000; i++)
+ for (i = 0xa000; i; i--)
{
bval = DC390_read8 (DMA_Status);
- DC390_write8 (DMA_Status, BLAST_COMPLETE | DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */
if (bval & BLAST_COMPLETE)
break;
}
- if (i == 0x8000) printk (KERN_CRIT "DC390: DMA Blast aborted unfinished!!\n");
+ /* It seems a DMA Blast abort isn't that bad ... */
+ if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
//DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
+ dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
- DEBUG1(printk ("Blast: Read %i times DMA_Status %02x", i, bval);)
+ DEBUG1(printk (KERN_DEBUG "Blast: Read %li times DMA_Status %02x", 0xa000-i, bval);)
ResidCnt = (ULONG) DC390_read8 (CtcReg_High);
ResidCnt <<= 8;
ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid);
@@ -525,7 +530,7 @@ din_1:
pSRB->TotalXferredLen++;
pSRB->SGToBeXferLen--;
}
- DEBUG1(printk ("Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
+ DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
pSRB->TotalXferredLen, pSRB->SGToBeXferLen);)
}
@@ -558,164 +563,278 @@ dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
}
-void
-dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
+
+static void __inline__
+dc390_reprog (PACB pACB, PDCB pDCB)
{
- UCHAR bval;
- USHORT wval, wval1;
- PDCB pDCB;
- PSRB psrb;
+ DC390_write8 (Sync_Period, pDCB->SyncPeriod);
+ DC390_write8 (Sync_Offset, pDCB->SyncOffset);
+ DC390_write8 (CtrlReg3, pDCB->CtrlR3);
+ DC390_write8 (CtrlReg4, pDCB->CtrlR4);
+ dc390_SetXferRate (pACB, pDCB);
+};
- pDCB = pACB->pActiveDCB;
- bval = DC390_read8 (ScsiFifo);
- if( !(pSRB->SRBState & SRB_MSGIN_MULTI) )
+#ifdef DC390_DEBUG0
+static void
+dc390_printMsg (UCHAR *MsgBuf, UCHAR len)
+{
+ int i;
+ printk (" %02x", MsgBuf[0]);
+ for (i = 1; i < len; i++)
+ printk (" %02x", MsgBuf[i]);
+ printk ("\n");
+};
+#endif
+
+#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
+
+/* reject_msg */
+static void __inline__
+dc390_MsgIn_reject (PACB pACB, PSRB pSRB)
+{
+ pSRB->MsgOutBuf[0] = MSG_REJECT_;
+ pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+ DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");)
+}
+
+/* abort command */
+static void __inline__
+dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB )
+{
+ pSRB->MsgOutBuf[0] = MSG_ABORT;
+ pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+ pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
+}
+
+static PSRB
+dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag)
+{
+ PSRB lastSRB = pDCB->pGoingLast;
+ PSRB pSRB = pDCB->pGoingSRB;
+
+ if (pSRB)
{
- if(bval == MSG_DISCONNECT)
- {
- pSRB->SRBState = SRB_DISCONNECT;
- }
- else if( bval == MSG_SAVE_PTR )
- goto min6;
- else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) &&
- (bval <= MSG_ORDER_QTAG)) )
+ for( ;pSRB ; )
{
- pSRB->SRBState |= SRB_MSGIN_MULTI;
- pSRB->MsgInBuf[0] = bval;
- pSRB->MsgCnt = 1;
- pSRB->pMsgPtr = &(pSRB->MsgInBuf[1]);
+ if (pSRB->TagNumber == tag) break;
+ if (pSRB == lastSRB) goto mingx0;
+ pSRB = pSRB->pNextSRB;
}
- else if(bval == MSG_REJECT_)
+
+ if( pDCB->DCBFlag & ABORT_DEV_ )
{
- DC390_write8 (ScsiCmd, RESET_ATN_CMD);
- pDCB->NegoPeriod = 50;
- if( pSRB->SRBState & DO_SYNC_NEGO)
- goto set_async;
+ pSRB->SRBState = SRB_ABORT_SENT;
+ dc390_EnableMsgOut_Abort( pACB, pSRB );
}
- else if( bval == MSG_RESTORE_PTR)
- goto min6;
- else
- goto min6;
+
+ if( !(pSRB->SRBState & SRB_DISCONNECT) )
+ goto mingx0;
+
+ pDCB->pActiveSRB = pSRB;
+ pSRB->SRBState = SRB_DATA_XFER;
}
- else
- { /* minx: */
+ else
+ {
+ mingx0:
+ pSRB = pACB->pTmpSRB;
+ pSRB->SRBState = SRB_UNEXPECT_RESEL;
+ pDCB->pActiveSRB = pSRB;
+ pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
+ pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
+ }
+ return pSRB;
+}
- *pSRB->pMsgPtr = bval;
- pSRB->MsgCnt++;
- pSRB->pMsgPtr++;
- if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) &&
- (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) )
- {
- if( pSRB->MsgCnt == 2)
- {
- pSRB->SRBState = 0;
- bval = pSRB->MsgInBuf[1];
- pSRB = pDCB->pGoingSRB;
- psrb = pDCB->pGoingLast;
- if( pSRB )
- {
- for( ;pSRB ; )
- {
- if(pSRB->TagNumber != bval)
- {
- if( pSRB == psrb )
- goto mingx0;
- pSRB = pSRB->pNextSRB;
- }
- else
- break;
- }
- if( pDCB->DCBFlag & ABORT_DEV_ )
- {
- pSRB->SRBState = SRB_ABORT_SENT;
- dc390_EnableMsgOut( pACB, pSRB );
- }
- if( !(pSRB->SRBState & SRB_DISCONNECT) )
- goto mingx0;
- pDCB->pActiveSRB = pSRB;
- pSRB->SRBState = SRB_DATA_XFER;
- }
- else
- {
-mingx0:
- pSRB = pACB->pTmpSRB;
- pSRB->SRBState = SRB_UNEXPECT_RESEL;
- pDCB->pActiveSRB = pSRB;
- pSRB->MsgOutBuf[0] = MSG_ABORT_TAG;
- dc390_EnableMsgOut2( pACB, pSRB );
- }
- }
+
+/* set async transfer mode */
+static void
+dc390_MsgIn_set_async (PACB pACB, PSRB pSRB)
+{
+ PDCB pDCB = pSRB->pSRBDCB;
+ if (!(pSRB->SRBState & DO_SYNC_NEGO))
+ printk ("DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID);
+ pSRB->SRBState &= ~DO_SYNC_NEGO;
+ pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
+ pDCB->SyncPeriod = 0;
+ pDCB->SyncOffset = 0;
+ //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
+ pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
+ pDCB->CtrlR4 &= 0x3f;
+ pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
+ dc390_reprog (pACB, pDCB);
+}
+
+/* set sync transfer mode */
+static void
+dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB)
+{
+ UCHAR bval;
+ USHORT wval, wval1;
+ PDCB pDCB = pSRB->pSRBDCB;
+ UCHAR oldsyncperiod = pDCB->SyncPeriod;
+ UCHAR oldsyncoffset = pDCB->SyncOffset;
+
+ if (!(pSRB->SRBState & DO_SYNC_NEGO))
+ {
+ printk ("DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
+ pDCB->UnitSCSIID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
+
+ /* reject */
+ //dc390_MsgIn_reject (pACB, pSRB);
+ //return dc390_MsgIn_set_async (pACB, pSRB);
+
+ /* Reply with corrected SDTR Message */
+ if (pSRB->MsgInBuf[4] > 15)
+ {
+ printk ("DC390: Lower Sync Offset to 15\n");
+ pSRB->MsgInBuf[4] = 15;
}
- else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) )
- { /* Note: This will fail for target initiated SDTR ? */
- pSRB->SRBState &= ~(SRB_MSGIN_MULTI);
- if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != EXTENDED_SDTR) )
- { /* reject_msg: */
- pSRB->MsgCnt = 1;
- pSRB->MsgInBuf[0] = MSG_REJECT_;
- DC390_write8 (ScsiCmd, SET_ATN_CMD);
- }
- else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) )
- {
-set_async:
- pDCB = pSRB->pSRBDCB;
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- printk ("DC390: Target (%i,%i) initiates Non-Sync?\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
- pDCB->SyncPeriod = 0;
- pDCB->SyncOffset = 0;
- pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 &= 0x3f;
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- goto re_prog;
- }
+ if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
+ {
+ printk ("DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2);
+ pSRB->MsgInBuf[3] = pDCB->NegoPeriod;
+ };
+ memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5);
+ pSRB->MsgCnt = 5;
+ DC390_ENABLE_MSGOUT;
+ };
+
+ pSRB->SRBState &= ~DO_SYNC_NEGO;
+ pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
+ pDCB->SyncOffset &= 0x0f0;
+ pDCB->SyncOffset |= pSRB->MsgInBuf[4];
+ pDCB->NegoPeriod = pSRB->MsgInBuf[3];
+
+ wval = (USHORT) pSRB->MsgInBuf[3];
+ wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
+ if( (wval1 * 25) != wval) wval1++;
+ bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
+
+ pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
+ if (pACB->glitch_cfg != NS_TO_GLITCH(0))
+ pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
+ else
+ pDCB->CtrlR4 |= NS_TO_GLITCH(0);
+ if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
+
+ if (wval1 >= 8)
+ {
+ wval1--; /* Timing computation differs by 1 from FAST_SCSI */
+ bval = FAST_CLK; /* fast clock / normal scsi */
+ pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
+ }
+
+ pDCB->CtrlR3 = bval;
+ pDCB->SyncPeriod = (UCHAR)wval1;
+
+ if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->UnitSCSILUN == 0)
+ {
+ if (! (bval & FAST_SCSI)) wval1++;
+ printk ("DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->UnitSCSIID,
+ 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
+ }
+
+ dc390_reprog (pACB, pDCB);
+};
+
+
+/* According to the docs, the AM53C974 reads the message and
+ * generates a Succesful Operation IRQ before asserting ACK for
+ * the last byte (how does it know whether it's the last ?) */
+/* The old code handled it in another way, indicating, that on
+ * every message byte an IRQ is generated and every byte has to
+ * be manually ACKed. Hmmm ? (KG, 98/11/28) */
+/* The old implementation was correct. Sigh! */
+
+/* Check if the message is complete */
+static UCHAR __inline__
+dc390_MsgIn_complete (UCHAR *msgbuf, ULONG len)
+{
+ if (*msgbuf == MSG_EXTENDED)
+ {
+ if (len < 2) return 0;
+ if (len < msgbuf[1] + 2) return 0;
+ }
+ else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages
+ if (len < 2) return 0;
+ return 1;
+}
+
+
+
+/* read and eval received messages */
+void
+dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus)
+{
+ PDCB pDCB = pACB->pActiveDCB;
+
+ /* Read the msg */
+
+ pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
+ //pSRB->SRBState = 0;
+
+ /* Msg complete ? */
+ if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
+ {
+ DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);)
+ /* Now eval the msg */
+ switch (pSRB->MsgInBuf[0])
+ {
+ case MSG_DISCONNECT:
+ pSRB->SRBState = SRB_DISCONNECT; break;
+
+ case MSG_SIMPLE_QTAG:
+ case MSG_HEAD_QTAG:
+ case MSG_ORDER_QTAG:
+ pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
+ break;
+
+ case MSG_REJECT_:
+ DC390_write8 (ScsiCmd, RESET_ATN_CMD);
+ pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
+ if( pSRB->SRBState & DO_SYNC_NEGO)
+ dc390_MsgIn_set_async (pACB, pSRB);
+ break;
+
+ case MSG_EXTENDED:
+ /* reject every extended msg but SDTR */
+ if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
+ dc390_MsgIn_reject (pACB, pSRB);
else
- { /* set_sync: */
-
- pDCB = pSRB->pSRBDCB;
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- printk ("DC390: Target (%i,%i) initiates Sync: %ins %i ?\n",
- pDCB->UnitSCSIID, pDCB->UnitSCSILUN, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
- pDCB->SyncOffset &= 0x0f0;
- pDCB->SyncOffset |= pSRB->MsgInBuf[4];
- pDCB->NegoPeriod = pSRB->MsgInBuf[3];
- wval = (USHORT) pSRB->MsgInBuf[3];
- wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
- if( (wval1 * 25) != wval)
- wval1++;
- bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
- pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
- if (pACB->glitch_cfg != NS_TO_GLITCH(0))
- pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
+ {
+ if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
+ dc390_MsgIn_set_async (pACB, pSRB);
else
- pDCB->CtrlR4 |= NS_TO_GLITCH(0);
- if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
- if (wval1 >= 8)
- {
- wval1--; /* Timing computation differs by 1 from FAST_SCSI */
- bval = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- }
- pDCB->CtrlR3 = bval;
- pDCB->SyncPeriod = (UCHAR)wval1;
-re_prog:
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- DC390_write8 (CtrlReg4, pDCB->CtrlR4);
- dc390_SetXferRate (pACB, pDCB);
- }
- }
- }
-min6:
+ dc390_MsgIn_set_sync (pACB, pSRB);
+ };
+
+ // nothing has to be done
+ case MSG_COMPLETE: break;
+
+ // SAVE POINTER my be ignored as we have the PSRB associated with the
+ // scsi command. Thanks, Gerard, for pointing it out.
+ case MSG_SAVE_PTR: break;
+ // The device might want to restart transfer with a RESTORE
+ case MSG_RESTORE_PTR:
+ printk ("DC390: RESTORE POINTER message received ... reject\n");
+ // fall through
+
+ // reject unknown messages
+ default: dc390_MsgIn_reject (pACB, pSRB);
+ }
+
+ /* Clear counter and MsgIn state */
+ pSRB->SRBState &= ~SRB_MSGIN;
+ pACB->MsgLen = 0;
+ };
+
*psstatus = SCSI_NOP0;
DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
}
+
void
dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
{
@@ -730,10 +849,10 @@ dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = virt_to_bus( psgl->address );
pSRB->SGToBeXferLen = (ULONG) psgl->length;
- DEBUG1(printk (" DC390: Next SG segment.");)
+ DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");)
}
lval = pSRB->SGToBeXferLen;
- DEBUG1(printk (" DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);)
+ DEBUG1(printk (KERN_DEBUG " DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);)
DC390_write8 (CtcReg_Low, (UCHAR) lval);
lval >>= 8;
DC390_write8 (CtcReg_Mid, (UCHAR) lval);
@@ -749,21 +868,22 @@ dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir)
DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
- //DEBUG1(printk ("DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));)
+ //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);)
+ //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));)
+ //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);)
}
else /* xfer pad */
{
- UCHAR bval = 0;
if( pSRB->SGcount )
{
pSRB->AdaptStatus = H_OVER_UNDER_RUN;
pSRB->SRBStatus |= OVER_RUN;
- DEBUG0(printk (" DC390: Overrun -");)
+ DEBUG0(printk (KERN_WARNING " DC390: Overrun -");)
}
- DEBUG0(printk (" Clear transfer pad \n");)
- DC390_write8 (CtcReg_Low, bval);
- DC390_write8 (CtcReg_Mid, bval);
- DC390_write8 (CtcReg_High, bval);
+ DEBUG0(printk (KERN_WARNING " Clear transfer pad \n");)
+ DC390_write8 (CtcReg_Low, 0);
+ DC390_write8 (CtcReg_Mid, 0);
+ DC390_write8 (CtcReg_High, 0);
pSRB->SRBState |= SRB_XFERPAD;
DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
@@ -1017,7 +1137,7 @@ disc1:
dc390_SRBdone( pACB, pDCB, pSRB);
}
}
- return;
+ pACB->MsgLen = 0;
}
@@ -1032,7 +1152,7 @@ dc390_Reselect( PACB pACB )
DEBUG0(printk(KERN_INFO "RSEL,");)
pDCB = pACB->pActiveDCB;
if( pDCB )
- { /* Arbitration lost but Reselection win */
+ { /* Arbitration lost but Reselection won */
DEBUG0(printk ("(ActiveDCB != 0)");)
pSRB = pDCB->pActiveSRB;
if( !( pACB->scan_devices ) )
@@ -1075,23 +1195,23 @@ dc390_Reselect( PACB pACB )
printk (KERN_ERR "DC390: Reselect without outstanding cmnd (ID %02x, LUN %02x)\n",
wval & 0xff, (wval & 0xff00) >> 8);
pDCB->pActiveSRB = pSRB;
- dc390_EnableMsgOut( pACB, pSRB );
+ dc390_EnableMsgOut_Abort ( pACB, pSRB );
}
else
{
if( pDCB->DCBFlag & ABORT_DEV_ )
{
pSRB->SRBState = SRB_ABORT_SENT;
- printk (KERN_NOTICE "DC390: Reselect: Abort (ID %02x, LUN %02x)\n",
+ printk (KERN_INFO "DC390: Reselect: Abort (ID %02x, LUN %02x)\n",
wval & 0xff, (wval & 0xff00) >> 8);
- dc390_EnableMsgOut( pACB, pSRB );
+ dc390_EnableMsgOut_Abort( pACB, pSRB );
}
else
pSRB->SRBState = SRB_DATA_XFER;
}
}
- DEBUG1(printk ("Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);)
+ DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);)
pSRB->ScsiPhase = SCSI_NOP0;
DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID);
DC390_write8 (Sync_Period, pDCB->SyncPeriod);
@@ -1244,7 +1364,7 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
else
pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) |
SCSI_STAT_CHECKCOND;
- REMOVABLEDEBUG(printk("Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\
+ REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\
(UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
goto ckc_e;
}
@@ -1260,7 +1380,7 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
{
pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16)
| SCSI_STAT_CHECKCOND;
- REMOVABLEDEBUG(printk("Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\
+ REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\
(UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);)
goto ckc_e;
}
@@ -1299,7 +1419,7 @@ dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB )
swlval += ptr2->length;
ptr2++;
}
- REMOVABLEDEBUG(printk("XferredLen=%08x,NotXferLen=%08x\n",\
+ REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\
(UINT) pSRB->TotalXferredLen, (UINT) swlval);)
}
dc390_RequestSense( pACB, pDCB, pSRB );
@@ -1587,22 +1707,6 @@ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB )
}
-static void __inline__
-dc390_EnableMsgOut2( PACB pACB, PSRB pSRB )
-{
- pSRB->MsgCnt = 1;
- DC390_write8 (ScsiCmd, SET_ATN_CMD);
-}
-
-
-static void __inline__
-dc390_EnableMsgOut( PACB pACB, PSRB pSRB )
-{
- pSRB->MsgOutBuf[0] = MSG_ABORT;
- dc390_EnableMsgOut2( pACB, pSRB );
- pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
static void __inline__
dc390_InvalidCmd( PACB pACB )
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a2d6056b9..13f511b96 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1482,12 +1482,11 @@ static int sd_init()
if (!rscsi_disks)
sd_template.dev_max = sd_template.dev_noticed + SD_EXTRA_DEVS;
- /* 128 disks is our current limit (8 majors, 16 disks per major) */
- if(sd_template.dev_max > 128)
- sd_template.dev_max = 128;
+ if(sd_template.dev_max > N_SD_MAJORS * SCSI_DISKS_PER_MAJOR )
+ sd_template.dev_max = N_SD_MAJORS * SCSI_DISKS_PER_MAJOR;
if(!sd_registered) {
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
if (register_blkdev(SD_MAJOR(i),"sd",&sd_fops)) {
printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i));
return 1;
@@ -1540,8 +1539,9 @@ static int sd_init()
sd_gendisks[i].real_devices =
(void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
}
+
LAST_SD_GENDISK.max_nr =
- sd_template.dev_max % SCSI_DISKS_PER_MAJOR;
+ (sd_template.dev_max -1 ) % SCSI_DISKS_PER_MAJOR + 1;
LAST_SD_GENDISK.next = NULL;
return 0;
}
@@ -1559,7 +1559,7 @@ static void sd_finish()
struct gendisk *gendisk;
int i;
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
/* FIXME: After 2.2 we should implement multiple sd queues */
blk_dev[SD_MAJOR(i)].request_fn = DEVICE_REQUEST;
if (i) blk_dev[SD_MAJOR(i)].queue = sd_get_queue;
@@ -1765,7 +1765,7 @@ void cleanup_module( void)
scsi_unregister_module(MODULE_SCSI_DEV, &sd_template);
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++)
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++)
unregister_blkdev(SD_MAJOR(i),"sd");
sd_registered--;
@@ -1794,11 +1794,11 @@ void cleanup_module( void)
if (removed != N_USED_SD_MAJORS)
printk("%s %d sd_gendisks in disk chain",
- removed > N_USED_SD_MAJORS ? "total" : "just", removed);
+ removed > N_USED_SD_MAJORS ? "total" : "just", removed);
}
- for (i=0; i <= sd_template.dev_max / SCSI_DISKS_PER_MAJOR; i++) {
+ for (i=0; i <= (sd_template.dev_max - 1) / SCSI_DISKS_PER_MAJOR; i++) {
blk_dev[SD_MAJOR(i)].request_fn = NULL;
blk_size[SD_MAJOR(i)] = NULL;
hardsect_size[SD_MAJOR(i)] = NULL;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 703fb42aa..ebfd9dda9 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -379,8 +379,8 @@ static void __init borken_init (void)
{
register int count = 0, start = jiffies + 1, stop = start + 25;
- while (jiffies < start) ;
- for (; jiffies < stop; ++count) ;
+ while (time_before(jiffies, start)) ;
+ for (; time_before(jiffies, stop); ++count) ;
/*
* Ok, we now have a count for .25 seconds. Convert to a
@@ -903,9 +903,9 @@ static int internal_command (unsigned char target, unsigned char lun,
while (((STATUS | STATUS | STATUS) &
(STAT_BSY | STAT_SEL)) &&
- (!st0x_aborted) && (jiffies < clock));
+ (!st0x_aborted) && time_before(jiffies, clock));
- if (jiffies > clock)
+ if (time_after(jiffies, clock))
return retcode (DID_BUS_BUSY);
else if (st0x_aborted)
return retcode (st0x_aborted);
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 2c8419358..d495363c5 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -63,7 +63,6 @@ Scsi_CD * scsi_CDs = NULL;
static int * sr_sizes = NULL;
static int * sr_blocksizes = NULL;
-static int * sr_hardsizes = NULL; /* Hardware sector size */
static int sr_open(struct cdrom_device_info*, int);
void get_sectorsize(int);
@@ -154,8 +153,7 @@ int sr_media_change(struct cdrom_device_info *cdi, int slot){
*/
scsi_CDs[MINOR(cdi->dev)].needs_sector_size = 1;
- scsi_CDs[MINOR(cdi->dev)].sector_size =
- sr_hardsizes[MINOR(cdi->dev)] = 2048;
+ scsi_CDs[MINOR(cdi->dev)].sector_size = 2048;
}
return retval;
}
@@ -955,7 +953,6 @@ void get_sectorsize(int i){
* Add this so that we have the ability to correctly gauge
* what the device is capable of.
*/
- sr_hardsizes[i] = scsi_CDs[i].sector_size;
scsi_CDs[i].needs_sector_size = 0;
sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
};
@@ -1040,16 +1037,12 @@ static int sr_init()
sr_blocksizes = (int *) scsi_init_malloc(sr_template.dev_max *
sizeof(int), GFP_ATOMIC);
- sr_hardsizes = (int *) scsi_init_malloc(sr_template.dev_max *
- sizeof(int), GFP_ATOMIC);
/*
* These are good guesses for the time being.
*/
for(i=0;i<sr_template.dev_max;i++) sr_blocksizes[i] = 2048;
- for(i=0;i<sr_template.dev_max;i++) sr_hardsizes[i] = 2048;
blksize_size[MAJOR_NR] = sr_blocksizes;
- hardsect_size[MAJOR_NR] = sr_hardsizes;
return 0;
}
@@ -1163,9 +1156,6 @@ void cleanup_module( void)
scsi_init_free((char *) sr_blocksizes, sr_template.dev_max * sizeof(int));
sr_blocksizes = NULL;
-
- scsi_init_free((char *) sr_hardsizes, sr_template.dev_max * sizeof(int));
- sr_hardsizes = NULL;
}
blksize_size[MAJOR_NR] = NULL;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 8ec3dbc06..8ffabde7e 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -11,7 +11,7 @@
Copyright 1992 - 1998 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Sun Sep 6 09:34:49 1998 by root@home
+ Last modified: Thu Dec 3 20:27:46 1998 by makisara@home
Some small formal changes - aeb, 950809
*/
@@ -707,7 +707,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
STp->density = 0; /* Clear the erroneous "residue" */
STp->write_prot = 0;
STp->block_size = 0;
- STp->ps[0].drv_file = STp->ps[0].drv_block = 0;
+ STp->ps[0].drv_file = STp->ps[0].drv_block = (-1);
STp->partition = STp->new_partition = 0;
STp->door_locked = ST_UNLOCKED;
STp->in_use = 1;
@@ -785,6 +785,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {
printk(KERN_NOTICE "st%d: Blocksize %d too large for buffer.\n", dev,
STp->block_size);
+ scsi_release_command(SCpnt);
(STp->buffer)->in_use = 0;
STp->buffer = NULL;
if (scsi_tapes[dev].device->host->hostt->module)
@@ -3414,8 +3415,8 @@ static int st_attach(Scsi_Device * SDp){
STps->eof = ST_NOEOF;
STps->at_sm = 0;
STps->last_block_valid = FALSE;
- STps->drv_block = 0;
- STps->drv_file = 0;
+ STps->drv_block = (-1);
+ STps->drv_file = (-1);
}
tpnt->current_mode = 0;
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index cafd9280c..af47e706c 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -5,9 +5,11 @@
* Bus Master Host Adapter *
* (C)Copyright 1995-1996 Tekram Technology Co., Ltd. *
***********************************************************************/
-/* $Id: tmscsim.c,v 2.4 1998/10/24 08:50:47 garloff Exp $ */
+/* (C) Copyright: put under GNU GPL in 10/96 *
+*************************************************************************/
+/* $Id: tmscsim.c,v 2.16 1998/12/25 17:54:44 garloff Exp $ */
/* Enhancements and bugfixes by *
- * Kurt Garloff <K.Garloff@ping.de> *
+ * Kurt Garloff <kurt@garloff.de> *
***********************************************************************/
/* HISTORY: *
* *
@@ -90,6 +92,11 @@
* bios_param() now respects part. table. *
* 2.0b 98/10/24 KG Docu fixes. Timeout Msg in DMA Blast. *
* Disallow illegal idx in INQUIRY/REMOVE *
+ * 2.0c 98/11/19 KG Cleaned up detect/init for SMP boxes, *
+ * Write Erase DMA (1.20t) caused problems *
+ * 2.0d 98/12/25 KG Christmas release ;-) Message handling *
+ * competely reworked. Handle target ini- *
+ * tiated SDTR correctly. *
***********************************************************************/
/* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */
@@ -206,9 +213,9 @@
# if USE_SPINLOCKS == 3 /* both */
# if defined (__SMP__) || DEBUG_SPINLOCKS > 0
-# define DC390_LOCK_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
+# define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
# else
-# define DC390_LOCK_INIT
+# define DC390_LOCKA_INIT
# endif
spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
@@ -228,16 +235,16 @@
# define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)
# define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))
# define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))
-//# define DC390_LOCK_INIT spin_lock_init (&(pACB->lock))
+//# define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))
# else
# if USE_SPINLOCKS == 2 /* adapter specific locks */
# if defined (__SMP__) || DEBUG_SPINLOCKS > 0
-# define DC390_LOCK_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
+# define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
# else
-# define DC390_LOCK_INIT
+# define DC390_LOCKA_INIT
# endif
spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;
# define DC390_AFLAGS unsigned long aflags;
@@ -253,7 +260,7 @@
# define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)
# define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))
# define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))
-//# define DC390_LOCK_INIT spin_lock_init (&(pACB->lock))
+//# define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))
# else /* USE_SPINLOCKS == 1: global lock io_request_lock */
@@ -271,7 +278,7 @@
# define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */
# define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */
# define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */
-# define DC390_LOCK_INIT /* DC390_LOCK_INIT */
+# define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */
# endif /* 2 */
# endif /* 3 */
@@ -291,7 +298,7 @@
# define DC390_UNLOCK_ACB restore_flags (aflags)
# define DC390_LOCK_ACB_NI
# define DC390_UNLOCK_ACB_NI
-# define DC390_LOCK_INIT
+# define DC390_LOCKA_INIT
#endif /* def */
@@ -365,9 +372,8 @@ void dc390_DoingSRB_Done( PACB pACB );
static void dc390_ScsiRstDetect( PACB pACB );
static void dc390_ResetSCSIBus( PACB pACB );
static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
-static void __inline__ dc390_EnableMsgOut2( PACB pACB, PSRB pSRB );
-static void __inline__ dc390_EnableMsgOut( PACB pACB, PSRB pSRB );
static void __inline__ dc390_InvalidCmd( PACB pACB );
+static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB);
static void dc390_remove_dev (PACB pACB, PDCB pDCB);
void do_DC390_Interrupt( int, void *, struct pt_regs *);
@@ -481,9 +487,190 @@ struct proc_dir_entry DC390_proc_scsi_tmscsim ={
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
+
/***********************************************************************
+ * Functions for access to DC390 EEPROM
+ * and some to emulate it
*
- *
+ **********************************************************************/
+
+
+static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval )
+{
+ UCHAR bval;
+
+ bval = 0;
+ if(mode == ENABLE_CE)
+ *regval = 0xc0;
+ else
+ *regval = 0x80;
+ PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
+ if(mode == DISABLE_CE)
+ PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
+ udelay(160);
+}
+
+#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
+static void __init dc390_EEpromDefaults (UCHAR index)
+{
+ PUCHAR ptr;
+ UCHAR id;
+ ptr = (PUCHAR) dc390_eepromBuf[index];
+
+ /* Adapter Settings */
+ ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */
+ ptr[EE_MODE2] = (UCHAR)tmscsim[3];
+ ptr[EE_DELAY] = 0; /* ?? */
+ ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Comds */
+
+ /* Device Settings */
+ for (id = 0; id < MAX_SCSI_ID; id++)
+ {
+ ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */
+ ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */
+ };
+ dc390_adapname = "AM53C974";
+}
+
+static void __init dc390_checkparams (void)
+{
+ PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x\n", tmscsim[0],\
+ tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4]);)
+ if (tmscsim[0] < 0 || tmscsim[0] > 7) /* modules-2.0.0 passes -1 as string */
+ {
+ tmscsim[0] = 7; tmscsim[1] = 4;
+ tmscsim[2] = 9; tmscsim[3] = 15;
+ tmscsim[4] = 2;
+ printk (KERN_INFO "DC390: Using safe settings.\n");
+ }
+ else
+ {
+ /* if (tmscsim[0] < 0 || tmscsim[0] > 7) tmscsim[0] = 7; */
+ if (tmscsim[1] < 0 || tmscsim[1] > 7) tmscsim[1] = 4;
+ if (tmscsim[4] < 0 || tmscsim[4] > 5) tmscsim[4] = 4;
+ };
+};
+/* Override defaults on cmdline:
+ * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped)
+ */
+void __init dc390_setup (char *str, int *ints)
+{
+ int i;
+ for (i = 0; i < ints[0]; i++)
+ tmscsim[i] = ints[i+1];
+ if (ints[0] > 5)
+ printk (KERN_NOTICE "DC390: ignore extra params!\n");
+ /* dc390_checkparams (); */
+};
+#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */
+
+
+static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry )
+{
+ UCHAR bval;
+
+ bval = 0;
+ if(Carry)
+ {
+ bval = 0x40;
+ *regval = 0x80;
+ PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
+ }
+ udelay(160);
+ bval |= 0x80;
+ PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
+ udelay(160);
+ bval = 0;
+ PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
+ udelay(160);
+}
+
+
+static UCHAR __init dc390_EEpromInDO( PDEVDECL )
+{
+ UCHAR bval;
+
+ PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80);
+ udelay(160);
+ PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40);
+ udelay(160);
+ PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval);
+ if(bval == 0x22)
+ return(1);
+ else
+ return(0);
+}
+
+
+static USHORT __init dc390_EEpromGetData1( PDEVDECL )
+{
+ UCHAR i;
+ UCHAR carryFlag;
+ USHORT wval;
+
+ wval = 0;
+ for(i=0; i<16; i++)
+ {
+ wval <<= 1;
+ carryFlag = dc390_EEpromInDO(PDEV);
+ wval |= carryFlag;
+ }
+ return(wval);
+}
+
+
+static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd )
+{
+ UCHAR i,j;
+ UCHAR carryFlag;
+
+ carryFlag = 1;
+ j = 0x80;
+ for(i=0; i<9; i++)
+ {
+ dc390_EEpromOutDI(PDEV,regval,carryFlag);
+ carryFlag = (EEpromCmd & j) ? 1 : 0;
+ j >>= 1;
+ }
+}
+
+
+static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr)
+{
+ UCHAR regval,cmd;
+ UCHAR i;
+
+ cmd = EEPROM_READ;
+ for(i=0; i<0x40; i++)
+ {
+ dc390_EnDisableCE(ENABLE_CE, PDEV, &regval);
+ dc390_Prepare(PDEV, &regval, cmd++);
+ *ptr++ = dc390_EEpromGetData1(PDEV);
+ dc390_EnDisableCE(DISABLE_CE, PDEV, &regval);
+ }
+}
+
+
+static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index )
+{
+ UCHAR i;
+ char EEbuf[128];
+ USHORT wval, *ptr = (PUSHORT)EEbuf;
+
+ dc390_ReadEEprom( PDEV, ptr );
+ memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
+ memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
+ &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
+ wval = 0;
+ for(i=0; i<0x40; i++, ptr++)
+ wval += *ptr;
+ return (wval == 0x1234 ? 0 : 1);
+}
+
+
+/***********************************************************************
+ * Functions for the management of the internal structures
+ * (DCBs, SRBs, Queueing)
*
**********************************************************************/
static PDCB __inline__ dc390_findDCB ( PACB pACB, Scsi_Cmnd *cmd)
@@ -494,7 +681,7 @@ static PDCB __inline__ dc390_findDCB ( PACB pACB, Scsi_Cmnd *cmd)
pDCB = pDCB->pNextDCB;
if (pDCB == pACB->pLinkDCB)
{
- printk (KERN_ERR "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n",
+ printk (KERN_WARNING "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n",
(int)pDCB, cmd->target, pACB->DCBmap[cmd->target]);
return 0;
}
@@ -578,7 +765,7 @@ static void dc390_RewaitSRB( PDCB pDCB, PSRB pSRB )
UCHAR bval;
pDCB->GoingSRBCnt--; pDCB->pDCBACB->SelLost++;
- DEBUG0(printk("DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);)
+ DEBUG0(printk(KERN_INFO "DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);)
psrb1 = pDCB->pGoingSRB;
if( pSRB == psrb1 )
{
@@ -678,6 +865,13 @@ static __inline__ void dc390_SRBwaiting( PDCB pDCB, PSRB pSRB)
}
+/***********************************************************************
+ * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB)
+ *
+ * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB)
+ *
+ ***********************************************************************/
+
static void dc390_SendSRB( PACB pACB, PSRB pSRB )
{
PDCB pDCB;
@@ -720,6 +914,14 @@ SND_EXIT:
return;
}
+/***********************************************************************
+ * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, PDCB pDCB,
+ * PSRB pSRB)
+ *
+ * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd
+ *
+ ***********************************************************************/
+
static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB)
{
pSRB->pSRBDCB = pDCB;
@@ -790,7 +992,7 @@ int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
DEBUG0(/* if(pACB->scan_devices) */ \
- printk(KERN_DEBUG "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\
+ printk(KERN_INFO "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\
cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);)
DC390_LOCK_ACB;
@@ -1056,15 +1258,17 @@ void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB)
printk (" %02x %02x %02x %02x %02x %02x\n",
DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
+ DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
printk ("DC390: Register dump: DMA engine:\n");
printk ("DC390: Cmd STrCnt SBusA WrkBC WrkAC Stat SBusCtrl\n");
printk ("DC390: %02x %08x %08x %08x %08x %02x %08x\n",
DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
+ DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat);
printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
- printk ("DC390: Please report driver trouble to K.Garloff@ping.de\n");
+ printk ("DC390: In case of driver trouble read linux/drivers/scsi/README.tmscsim\n");
};
@@ -1076,6 +1280,8 @@ void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB)
* Inputs : cmd - command to abort
*
* Returns : 0 on success, -1 on failure.
+ *
+ * Status: Buggy !
***********************************************************************/
int DC390_abort (Scsi_Cmnd *cmd)
@@ -1347,13 +1553,13 @@ int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags)
/***********************************************************************
- * Function : static void dc390_initDCB
+ * Function : static void dc390_initDCB()
*
* Purpose : initialize the internal structures for a given DCB
*
* Inputs : cmd - pointer to this scsi cmd request block structure
- *
***********************************************************************/
+
void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd )
{
PEEprom prom;
@@ -1412,11 +1618,11 @@ void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd )
}
/***********************************************************************
- * Function : static void dc390_updateDCB
+ * Function : static void dc390_updateDCB()
*
* Purpose : Set the configuration dependent DCB parameters
- *
***********************************************************************/
+
void dc390_updateDCB (PACB pACB, PDCB pDCB)
{
pDCB->IdentifyMsg = IDENTIFY (pDCB->DevMode & EN_DISCONNECT_, pDCB->UnitSCSILUN);
@@ -1441,11 +1647,11 @@ void dc390_updateDCB (PACB pACB, PDCB pDCB)
/***********************************************************************
- * Function : static void dc390_updateDCBs
+ * Function : static void dc390_updateDCBs ()
*
* Purpose : Set the configuration dependent DCB params for all DCBs
- *
***********************************************************************/
+
static void dc390_updateDCBs (PACB pACB)
{
int i;
@@ -1459,13 +1665,13 @@ static void dc390_updateDCBs (PACB pACB)
/***********************************************************************
- * Function : static void dc390_initSRB
+ * Function : static void dc390_initSRB()
*
* Purpose : initialize the internal structures for a given SRB
*
* Inputs : psrb - pointer to this scsi request block structure
- *
***********************************************************************/
+
static void __inline__ dc390_initSRB( PSRB psrb )
{
/* psrb->PhysSRB = virt_to_phys( psrb ); */
@@ -1489,13 +1695,14 @@ void dc390_linkSRB( PACB pACB )
/***********************************************************************
- * Function : static void dc390_initACB
+ * Function : static void dc390_initACB ()
*
* Purpose : initialize the internal structures for a given SCSI host
*
* Inputs : psh - pointer to this host adapter's structure
- *
+ * io_port, Irq, index: Resources and adapter index
***********************************************************************/
+
void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
{
PACB pACB;
@@ -1510,14 +1717,14 @@ void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
psh->irq = Irq;
pACB = (PACB) psh->hostdata;
- DC390_LOCK_INIT;
+ DC390_LOCKA_INIT;
DC390_LOCK_ACB;
pACB->pScsiHost = psh;
pACB->IOPortBase = (USHORT) io_port;
pACB->IRQLevel = Irq;
- DEBUG0(printk (KERN_DEBUG "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \
+ DEBUG0(printk (KERN_INFO "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \
index, psh->this_id, (int)io_port, Irq);)
psh->max_id = 8;
@@ -1541,6 +1748,8 @@ void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM];
pACB->ACBFlag = 0;
pACB->scan_devices = 1;
+ pACB->MsgLen = 0;
+ pACB->Ignore_IRQ = 0;
pACB->Gmode2 = dc390_eepromBuf[index][EE_MODE2];
dc390_linkSRB( pACB );
pACB->pTmpSRB = &pACB->TmpSRB;
@@ -1554,33 +1763,44 @@ void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
/***********************************************************************
- * Function : static int dc390_initAdapter
+ * Function : static int dc390_initAdapter ()
*
* Purpose : initialize the SCSI chip ctrl registers
*
* Inputs : psh - pointer to this host adapter's structure
+ * io_port, Irq, index: Resources
*
+ * Outputs: 0 on success, -1 on error
***********************************************************************/
+
int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
{
- PACB pACB, pacb;
+ PACB pACB, pACB2;
UCHAR used_irq = 0, dstate;
int i;
+
+ pACB = (PACB) psh->hostdata;
+
+ for ( pACB2 = dc390_pACB_start; pACB2 ; )
+ {
+ if( pACB2->IRQLevel == Irq )
+ {
+ used_irq = 1;
+ break;
+ }
+ else
+ pACB2 = pACB2->pNextACB;
+ }
- pacb = dc390_pACB_start;
- if( pacb != NULL )
- {
- for ( ; (pacb != (PACB) -1) ; )
+ if (check_region (io_port, psh->n_io_port))
{
- if( pacb->IRQLevel == Irq )
- {
- used_irq = 1;
- break;
- }
- else
- pacb = pacb->pNextACB;
+ printk(KERN_ERR "DC390: register IO ports error!\n");
+ return( -1 );
}
- }
+ else
+ request_region (io_port, psh->n_io_port, "tmscsim");
+
+ DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */
if( !used_irq )
{
@@ -1591,18 +1811,22 @@ int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
}
}
- if (check_region (io_port, psh->n_io_port))
- {
- printk(KERN_ERR "DC390: register IO ports error!\n");
- return( -1 );
- }
+ if( !dc390_pACB_start )
+ {
+ pACB2 = NULL;
+ dc390_pACB_start = pACB;
+ dc390_pACB_current = pACB;
+ pACB->pNextACB = NULL;
+ }
else
- request_region (io_port, psh->n_io_port, "tmscsim");
-
- pACB = (PACB) psh->hostdata;
- /* pACB->IOPortBase = (USHORT) io_port; */
+ {
+ pACB2 = dc390_pACB_current;
+ dc390_pACB_current->pNextACB = pACB;
+ dc390_pACB_current = pACB;
+ pACB->pNextACB = NULL;
+ };
- DC390_write8_ (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id, io_port); /* Disable SCSI bus reset interrupt */
+ DC390_write8 (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id); /* Disable SCSI bus reset interrupt */
if (pACB->Gmode2 & RST_SCSI_BUS)
{
@@ -1612,6 +1836,7 @@ int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
udelay(1000);
};
pACB->ACBFlag = 0;
+ DC390_read8 (INT_Status); /* Reset Pending INT */
DC390_write8 (Scsi_TimeOut, SEL_TIMEOUT); /* 250ms selection timeout */
DC390_write8 (Clk_Factor, CLK_FREQ_40MHZ); /* Conversion factor = 0 , 40MHz clock */
@@ -1622,7 +1847,7 @@ int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
(dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0); /* Negation */
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
+ DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
dstate = DC390_read8 (DMA_Status);
DC390_write8 (DMA_Status, dstate); /* clear */
@@ -1630,194 +1855,24 @@ int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
}
-static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval )
-{
- UCHAR bval;
-
- bval = 0;
- if(mode == ENABLE_CE)
- *regval = 0xc0;
- else
- *regval = 0x80;
- PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
- if(mode == DISABLE_CE)
- PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
- udelay(160);
-}
-
-#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
-static void __init dc390_EEpromDefaults (UCHAR index)
-{
- PUCHAR ptr;
- UCHAR id;
- ptr = (PUCHAR) dc390_eepromBuf[index];
-
- /* Adapter Settings */
- ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */
- ptr[EE_MODE2] = (UCHAR)tmscsim[3];
- ptr[EE_DELAY] = 0; /* ?? */
- ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Comds */
-
- /* Device Settings */
- for (id = 0; id < MAX_SCSI_ID; id++)
- {
- ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */
- ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */
- };
- dc390_adapname = "AM53C974";
-}
-
-static void __init dc390_checkparams (void)
-{
- PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x\n", tmscsim[0],\
- tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4]);)
- if (tmscsim[0] < 0 || tmscsim[0] > 7) /* modules-2.0.0 passes -1 as string */
- {
- tmscsim[0] = 7; tmscsim[1] = 4;
- tmscsim[2] = 9; tmscsim[3] = 15;
- tmscsim[4] = 2;
- printk (KERN_INFO "DC390: Using safe settings.\n");
- }
- else
- {
- /* if (tmscsim[0] < 0 || tmscsim[0] > 7) tmscsim[0] = 7; */
- if (tmscsim[1] < 0 || tmscsim[1] > 7) tmscsim[1] = 4;
- if (tmscsim[4] < 0 || tmscsim[4] > 5) tmscsim[4] = 4;
- };
-};
-/* Override defaults on cmdline:
- * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped)
- */
-void __init dc390_setup (char *str, int *ints)
-{
- int i;
- for (i = 0; i < ints[0]; i++)
- tmscsim[i] = ints[i+1];
- if (ints[0] > 5)
- printk (KERN_NOTICE "DC390: ignore extra params!\n");
- /* dc390_checkparams (); */
-};
-#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */
-
-
-static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry )
-{
- UCHAR bval;
-
- bval = 0;
- if(Carry)
- {
- bval = 0x40;
- *regval = 0x80;
- PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
- }
- udelay(160);
- bval |= 0x80;
- PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
- udelay(160);
- bval = 0;
- PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval);
- udelay(160);
-}
-
-
-static UCHAR __init dc390_EEpromInDO( PDEVDECL )
-{
- UCHAR bval;
-
- PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80);
- udelay(160);
- PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40);
- udelay(160);
- PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval);
- if(bval == 0x22)
- return(1);
- else
- return(0);
-}
-
-
-static USHORT __init dc390_EEpromGetData1( PDEVDECL )
-{
- UCHAR i;
- UCHAR carryFlag;
- USHORT wval;
-
- wval = 0;
- for(i=0; i<16; i++)
- {
- wval <<= 1;
- carryFlag = dc390_EEpromInDO(PDEV);
- wval |= carryFlag;
- }
- return(wval);
-}
-
-
-static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd )
-{
- UCHAR i,j;
- UCHAR carryFlag;
-
- carryFlag = 1;
- j = 0x80;
- for(i=0; i<9; i++)
- {
- dc390_EEpromOutDI(PDEV,regval,carryFlag);
- carryFlag = (EEpromCmd & j) ? 1 : 0;
- j >>= 1;
- }
-}
-
-
-static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr)
-{
- UCHAR regval,cmd;
- UCHAR i;
-
- cmd = EEPROM_READ;
- for(i=0; i<0x40; i++)
- {
- dc390_EnDisableCE(ENABLE_CE, PDEV, &regval);
- dc390_Prepare(PDEV, &regval, cmd++);
- *ptr++ = dc390_EEpromGetData1(PDEV);
- dc390_EnDisableCE(DISABLE_CE, PDEV, &regval);
- }
-}
-
-
-static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index )
-{
- UCHAR i;
- char EEbuf[128];
- USHORT wval, *ptr = (PUSHORT)EEbuf;
-
- dc390_ReadEEprom( PDEV, ptr );
- memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
- memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
- &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
- wval = 0;
- for(i=0; i<0x40; i++, ptr++)
- wval += *ptr;
- return (wval == 0x1234 ? 0 : 1);
-}
-
-
/***********************************************************************
- * Function : static int DC390_init (struct Scsi_Host *host)
+ * Function : static int DC390_init (struct Scsi_Host *host, ...)
*
* Purpose : initialize the internal structures for a given SCSI host
*
- * Inputs : host - pointer to this host adapter's structure/
+ * Inputs : host - pointer to this host adapter's structure
+ * io_port - IO ports mapped to this adapter
+ * Irq - IRQ assigned to this adpater
+ * PDEVDECL - PCI access handle
+ * index - Adapter index
*
- * Preconditions : when this function is called, the chip_type
- * field of the pACB structure MUST have been set.
+ * Outputs: 0 on success, -1 on error
*
* Note: written in capitals, because the locking is only done here,
* not in DC390_detect, called from outside
***********************************************************************/
-static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, int index)
+static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, UCHAR index)
{
PSH psh;
PACB pACB;
@@ -1846,7 +1901,7 @@ static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, int
if( !psh ) return( -1 );
pACB = (PACB) psh->hostdata;
- DC390_LOCK_INIT;
+ DC390_LOCKA_INIT;
DC390_LOCK_ACB;
#if 0
@@ -1862,37 +1917,21 @@ static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, int
}
#endif
- DEBUG0(printk("DC390: pSH = %8x,", (UINT) psh);)
- DEBUG0(printk("DC390: Index %02i,", index);)
+ DEBUG0(printk(KERN_INFO "DC390: pSH = %8x,", (UINT) psh);)
+ DEBUG0(printk(" Index %02i,", index);)
dc390_initACB( psh, io_port, Irq, index );
+ pACB = (PACB) psh->hostdata;
+
PDEVSET;
- DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */
-
if( !dc390_initAdapter( psh, io_port, Irq, index ) )
{
- pACB = (PACB) psh->hostdata;
- if( !dc390_pACB_start )
- {
- dc390_pACB_start = pACB;
- dc390_pACB_current = pACB;
- pACB->pNextACB = (PACB) -1;
- }
- else
- {
- dc390_pACB_current->pNextACB = pACB;
- dc390_pACB_current = pACB;
- pACB->pNextACB = (PACB) -1;
- }
-
- DEBUG0(printk("DC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\
+ DEBUG0(printk("\nDC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\
(UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array);)
DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\
sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );)
- DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */
-
DC390_UNLOCK_ACB;
return (0);
}
@@ -1960,7 +1999,6 @@ int __init DC390_detect (Scsi_Host_Template *psht)
PDEVDECL0;
UCHAR irq;
UINT io_port;
- UCHAR adaptCnt = 0; /* Number of boards detected */
DC390_IFLAGS DC390_DFLAGS
DC390_LOCK_DRV;
@@ -1972,29 +2010,36 @@ int __init DC390_detect (Scsi_Host_Template *psht)
{
DC390_LOCK_IO; /* Remove this when going to new eh */
PCI_GET_IO_AND_IRQ;
- DEBUG0(printk(KERN_DEBUG "DC390(%i): IO_PORT=%04x,IRQ=%x\n", adaptCnt, (UINT) io_port, irq);)
+ DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);)
- if( !DC390_init(psht, io_port, irq, PDEV, adaptCnt))
+ if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt))
{
PCI_SET_MASTER;
dc390_set_pci_cfg (PDEV);
- adaptCnt++;
+ dc390_adapterCnt++;
};
DC390_UNLOCK_IO; /* Remove when going to new eh */
}
else
printk (KERN_ERR "DC390: No PCI BIOS found!\n");
- if (adaptCnt)
+ if (dc390_adapterCnt)
psht->proc_dir = &DC390_proc_scsi_tmscsim;
- printk(KERN_INFO "DC390: %i adapters found\n", adaptCnt);
- dc390_adapterCnt = adaptCnt;
+ printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt);
DC390_UNLOCK_DRV;
- return( adaptCnt );
+ return( dc390_adapterCnt );
}
+/***********************************************************************
+ * Functions: dc390_inquiry(), dc390_inquiry_done()
+ *
+ * Purpose: When changing speed etc., we have to issue an INQUIRY
+ * command to make sure, we agree upon the nego parameters
+ * with the device
+ ***********************************************************************/
+
static void dc390_inquiry_done (Scsi_Cmnd* cmd)
{
printk (KERN_INFO "DC390: INQUIRY (ID %02x LUN %02x) returned %08x\n",
@@ -2211,7 +2256,7 @@ int dc390_set_info (char *buffer, int length, PACB pACB)
/* NegoPeriod */
if (*pos != '-')
{
- SCANF (pos, p0, dum, 76, 800);
+ SCANF (pos, p0, dum, 72, 800);
pDCB->NegoPeriod = dum >> 2;
if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
if (!pos) goto ok;
@@ -2367,8 +2412,6 @@ int dc390_set_info (char *buffer, int length, PACB pACB)
*
********************************************************************/
-/* KG: proc_info taken from driver aha152x.c */
-
#undef SPRINTF
#define SPRINTF(args...) pos += sprintf(pos, ## args)
@@ -2529,14 +2572,14 @@ int DC390_release(struct Scsi_Host *host)
if (host->irq != IRQ_NONE)
{
for (irq_count = 0, pACB = dc390_pACB_start;
- pACB && pACB != (PACB)-1; pACB = pACB->pNextACB)
+ pACB; pACB = pACB->pNextACB)
{
if ( pACB->IRQLevel == host->irq )
++irq_count;
}
if (irq_count == 1)
{
- DEBUG0(printk(KERN_DEBUG "DC390: Free IRQ %i\n",host->irq);)
+ DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);)
free_irq(host->irq,NULL);
}
}
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
index 6cee55837..acc6526fd 100644
--- a/drivers/scsi/tmscsim.h
+++ b/drivers/scsi/tmscsim.h
@@ -3,7 +3,7 @@
;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter *
;* Device Driver *
;***********************************************************************/
-/* $Id: tmscsim.h,v 2.1 1998/10/14 10:31:48 garloff Exp $ */
+/* $Id: tmscsim.h,v 2.4 1998/12/25 17:33:27 garloff Exp $ */
#ifndef _TMSCSIM_H
#define _TMSCSIM_H
@@ -95,15 +95,13 @@ UCHAR MsgOutBuf[6];
/* 0x48: */
SGL Segmentx; /* make a one entry of S/G list table */
-PUCHAR pMsgPtr;
-
UCHAR ScsiCmdLen;
UCHAR ScsiPhase;
UCHAR AdaptStatus;
UCHAR TargetStatus;
-/* 0x5c: */
+/* 0x58: */
UCHAR MsgCnt;
UCHAR EndMessage;
UCHAR RetryCnt;
@@ -115,7 +113,7 @@ UCHAR SGIndex;
UCHAR SRBStatus;
//UCHAR IORBFlag; /*;81h-Reset, 2-retry */
-/* 0x64: */
+/* 0x60: */
};
@@ -218,14 +216,16 @@ spinlock_t lock;
UCHAR sel_timeout;
UCHAR glitch_cfg;
-UCHAR reserved[2]; /* alignment */
+UCHAR MsgLen;
+UCHAR Ignore_IRQ; /* Not used */
PDEVDECL1; /* Pointer to PCI cfg. space */
-/* 0x44/0x40: */
+/* 0x40/0x3c: */
ULONG Cmds;
ULONG CmdInQ;
ULONG CmdOutOfSRB;
ULONG SelLost;
+
/* 0x50/0x4c: */
DC390_SRB TmpSRB;
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index 3ce29e72b..7338feeec 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -105,7 +105,7 @@
* 08/24/1996.
*
* Enhancement for wd7000_detect function has been made, so you don't have
- * to enter BIOS ROM adress in initialisation data (see struct Config).
+ * to enter BIOS ROM address in initialisation data (see struct Config).
* We cannot detect IRQ, DMA and I/O base address for now, so we have to
* enter them as arguments while wd_7000 is detected. If someone has IRQ,
* DMA or I/O base address set to some other value, he can enter them in
@@ -791,7 +791,7 @@ static inline short WAIT (unsigned port, unsigned mask, unsigned allof, unsigned
register unsigned WAITbits;
register unsigned long WAITtimeout = jiffies + WAITnexttimeout;
- while (jiffies <= WAITtimeout) {
+ while (time_before_eq(jiffies, WAITtimeout)) {
WAITbits = inb (port) & mask;
if (((WAITbits & allof) == allof) && ((WAITbits & noneof) == 0))
@@ -806,7 +806,7 @@ static inline void delay (unsigned how_long)
{
register unsigned long time = jiffies + how_long;
- while (jiffies < time);
+ while (time_before(jiffies, time));
}
@@ -868,7 +868,7 @@ static inline Scb *alloc_scbs (int needed)
spin_unlock_irq(&io_request_lock);
for (now = jiffies; now == jiffies; ); /* wait a jiffy */
spin_lock_irq(&io_request_lock);
- } while (freescbs < needed && jiffies <= timeout);
+ } while (freescbs < needed && time_before_eq(jiffies, timeout));
/*
* If we get here with enough free Scbs, we can take them.
* Otherwise, we timed out and didn't get enough.
@@ -1247,7 +1247,7 @@ int wd7000_diagnostics (Adapter *host, int code)
*/
mail_out (host, (struct scb *) &icb);
timeout = jiffies + WAITnexttimeout; /* wait up to 2 seconds */
- while (icb.phase && jiffies < timeout)
+ while (icb.phase && time_before(jiffies, timeout))
barrier (); /* wait for completion */
if (icb.phase) {
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index c7de93a50..3fd4832cd 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -20,6 +20,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate 'SGI Indy HAL2' CONFIG_SOUND_HAL2 $CONFIG_SOUND
fi
fi
+dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
dep_tristate 'Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND
if [ "$CONFIG_SOUND_MSNDCLAS" = "y" -o "$CONFIG_SOUND_MSNDCLAS" = "m" ]; then
@@ -128,7 +129,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
int 'PSS MIDI IRQ 3, 4, 5, 7, 9, 10, 11, 12' CONFIG_PSS_MPU_IRQ 9
bool ' Have DSPxxx.LD firmware file' CONFIG_PSS_HAVE_BOOT
if [ "$CONFIG_PSS_HAVE_BOOT" = "y" ]; then
- string ' Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE
+ string ' Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld
fi
fi
if [ "$CONFIG_SOUND_PSS" = "y" -o "$CONFIG_SOUND_PSS" = "m" ]; then
@@ -165,7 +166,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
int 'TRIX SB DMA 1 or 3' CONFIG_TRIX_SB_DMA 1
bool ' Have TRXPRO.HEX firmware file' CONFIG_TRIX_HAVE_BOOT
if [ "$CONFIG_TRIX_HAVE_BOOT" = "y" ]; then
- string ' Full pathname of TRXPRO.HEX firmware file' CONFIG_TRIX_BOOT_FILE
+ string ' Full pathname of TRXPRO.HEX firmware file' CONFIG_TRIX_BOOT_FILE /etc/sound/trxpro.hex
fi
fi
@@ -182,7 +183,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
int 'MAD16 MIDI IRQ 5, 7, 9 or 10' CONFIG_MAD16_MPU_IRQ 9
fi
- dep_tristate 'Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS
+ dep_tristate 'Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS m
if [ "$CONFIG_SOUND_WAVEFRONT" = "y" ]; then
hex 'I/O base for WaveFront 210, 230, 260, 290, 300, 320, 338 or 330' CONFIG_WAVEFRONT_BASE 330
int 'WaveFront IRQ 5, 9, 12 or 15' CONFIG_WAVEFRONT_IRQ 9
@@ -198,13 +199,15 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_MPU_IRQ 9
fi
- dep_tristate 'Support for Yamaha OPL3-SA[2,3,x] based (PnP) cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
+ dep_tristate 'Support for Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
if [ "$CONFIG_SOUND_OPL3SA2" = "y" ]; then
- hex 'OPL3SA2 audio I/O base 530, 604, E80 or F40' CONFIG_OPL3SA2_BASE 530
- int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 11
+ int 'Chipset (-1 for autoprobe, 2, or 3)' CONFIG_OPL3SA2_CHIPSET -1
+ hex 'OPL3SA2 audio I/O base (530 - F48 valid)' CONFIG_OPL3SA2_BASE 530
+ int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 9
int 'OPL3SA2 audio DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA 0
int 'OPL3SA2 second (duplex) DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA2 1
- hex 'OPL3SA2 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_OPL3SA2_MPU_BASE 330
+ hex 'OPL3SA2 control I/O base (100 - FFE valid)' CONFIG_OPL3SA2_CTRL_BASE 370
+ hex 'OPL3SA2 MIDI I/O base (300 - 334 valid)' CONFIG_OPL3SA2_MPU_BASE 330
int 'OPL3SA2 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_MPU_IRQ 9
fi
@@ -214,7 +217,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
int 'Maui IRQ 5, 9, 12 or 15' CONFIG_MAUI_IRQ 9
bool ' Have OSWF.MOT firmware file' CONFIG_MAUI_HAVE_BOOT
if [ "$CONFIG_MAUI_HAVE_BOOT" = "y" ]; then
- string ' Full pathname of OSWF.MOT firmware file' CONFIG_MAUI_BOOT_FILE
+ string ' Full pathname of OSWF.MOT firmware file' CONFIG_MAUI_BOOT_FILE /etc/sound/oswf.mot
fi
fi
@@ -227,6 +230,17 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
int 'SGALAXY second (duplex) DMA 0, 1 or 3' CONFIG_SGALAXY_DMA2 3
hex 'SGALAXY SB I/O base 220 or 240' CONFIG_SGALAXY_SGBASE 220
fi
+
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ dep_tristate 'Support for AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND
+ if [ "$CONFIG_SOUND_AD1816" = "y" ]; then
+ hex 'AD1816 audio I/O base 530, 604, E80 or F40' CONFIG_AD1816_BASE 530
+ int 'AD1816 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_AD1816_IRQ 7
+ int 'AD1816 audio DMA 0, 1 or 3' CONFIG_AD1816_DMA 0
+ int 'AD1816 second (duplex) DMA 0, 1 or 3' CONFIG_AD1816_DMA2 3
+ int 'AD1816 clock chip frequency' CONFIG_AD1816_CLOCK 33000
+ fi
+ fi
dep_tristate 'Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
if [ "$CONFIG_SOUND_OPL3SA1" = "y" ]; then
@@ -255,7 +269,14 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
fi
if [ "$CONFIG_ARM" = "y" ]; then
- bool 'VIDC 16-bit sound' CONFIG_VIDC_SOUND
+ dep_tristate 'VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
+ dep_tristate 'Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS
+ if [ "$CONFIG_SOUND_WAVEARTIST" != "n" ]; then
+ hex ' WaveArtist I/O base' CONFIG_WAVEARTIST_BASE 250
+ int ' WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 28
+ int ' WaveArtist DMA' CONFIG_WAVEARTIST_DMA 3
+ int ' WaveArtist second DMA' CONFIG_WAVEARTIST_DMA2 7
+ fi
fi
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index b76e03ce3..7cbf2f014 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -24,8 +24,7 @@ endif
export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
msnd.o opl3.o sb_card.o sequencer_syms.o \
- sound_core.o sound_firmware.o sound_syms.o \
- uart401.o
+ sound_core.o sound_syms.o uart401.o ad1816.o
@@ -66,13 +65,16 @@ obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_SB) += sb.o uart401.o
obj-$(CONFIG_SOUND_SOFTOSS) += softoss2.o
obj-$(CONFIG_SOUND_SGALAXY) += sgalaxy.o
+obj-$(CONFIG_SOUND_AD1816) += ad1816.o
obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb.o uart401.o
obj-$(CONFIG_SOUND_UART6850) += uart6850.o
obj-$(CONFIG_SOUND_VMIDI) += v_midi.o
obj-$(CONFIG_SOUND_YM3812) += adlib_card.o opl3.o
-obj-$(CONFIG_VIDC_SOUND) += vidc_mod.o
+obj-$(CONFIG_SOUND_VIDC) += vidc_mod.o
+obj-$(CONFIG_SOUND_WAVEARTIST) += waveartist.o
obj-$(CONFIG_SOUND_WAVEFRONT) += wavefront.o
+
#jnx
obj-$(CONFIG_SOUND_ES1370) += es1370.o
obj-$(CONFIG_SOUND_ES1371) += es1371.o
@@ -94,7 +96,8 @@ soundcore-objs := sound_core.o sound_firmware.o
gus-objs := gus_card.o gus_midi.o gus_vol.o gus_wave.o ics2101.o
pas2-objs := pas2_card.o pas2_midi.o pas2_mixer.o pas2_pcm.o
-sb-objs := sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o
+sb-objs := sb_audio.o sb_card.o sb_common.o sb_midi.o sb_mixer.o \
+ sb_ess.o
softoss2-objs := softoss.o softoss_rs.o
vidc_mod-objs := vidc.o vidc_audio.o vidc_fill.o vidc_mixer.o vidc_synth.o
wavefront-objs := wavfront.o wf_midi.o yss225.o
@@ -294,7 +297,7 @@ trix.o: trix_boot.h
ifeq ($(CONFIG_TRIX_HAVE_BOOT),y)
trix_boot.h: $(patsubst "%", %, $(CONFIG_TRIX_BOOT_FILE)) hex2hex
- hex2hex -i trix_boot < $(CONFIG_TRIX_BOOT_FILE) > $@
+ ./hex2hex -i trix_boot < $(CONFIG_TRIX_BOOT_FILE) > $@
else
trix_boot.h:
( \
diff --git a/drivers/sound/README.FIRST b/drivers/sound/README.FIRST
index 85ecccdfc..90fdcf063 100644
--- a/drivers/sound/README.FIRST
+++ b/drivers/sound/README.FIRST
@@ -4,4 +4,3 @@ Hannu's code. Please bear that in mind when considering the appropriate
forums for bug reporting.
Alan Cox
-
diff --git a/drivers/sound/README.blurb b/drivers/sound/README.blurb
deleted file mode 100644
index 5203d3fbe..000000000
--- a/drivers/sound/README.blurb
+++ /dev/null
@@ -1,10 +0,0 @@
-*********************************************************
-* Readme.cards (this directory) contains some card *
-* specific instructions. *
-* See http://www.4front-tech.com/ossfree for most up *
-* to date info. *
-* (European mirror http://personal.eunet.fi/pp/voxware) *
-* *
-* DON'T USE PROGRAMS FROM snd-util PACKAGE EARLIER THAN *
-* snd-util-3.5 WITH THIS SOUND DRIVER VERSION. *
-*********************************************************
diff --git a/drivers/sound/README.wavefront b/drivers/sound/README.wavefront
deleted file mode 100644
index 9e39f5d8d..000000000
--- a/drivers/sound/README.wavefront
+++ /dev/null
@@ -1,375 +0,0 @@
- An OSS/Free Driver for WaveFront Sound Cards
- (Turtle Beach Maui, Tropez, Tropez Plus)
-
- Paul Barton-Davis, July 1998
-
- VERSION 0.2.2
-
-Driver Status
--------------
-
-Requires: Kernel 2.1.106 or later
-
-As of 7/13/1998, this driver is currently in *BETA* state. This means
-that it compiles and runs, and that I use it on my system (Linux
-2.1.106) with some reasonably demanding applications and uses. I
-believe the code is approaching an initial "finished" state that
-provides bug-free support for the Tropez Plus.
-
-Please note that to date, the driver has ONLY been tested on a Tropez
-Plus. I would very much like to hear (and help out) people with Tropez
-and Maui cards, since I think the driver can support those cards as
-well.
-
-Finally, the driver has not been tested as a static (non-modular) part
-of the kernel. Alan Cox's good work in modularizing OSS/Free for Linux
-makes this rather unnecessary.
-
-Some Questions
---------------
-
-**********************************************************************
-0) What does this driver do that the maui driver did not ?
-**********************************************************************
-
-* can fully initialize a WaveFront card from cold boot - no DOS
- utilities needed
-* working patch/sample/program loading and unloading (the maui
- driver didn't document how to make this work, and assumed
- user-level preparation of the patch data for writing
- to the board. ick.)
-* full user-level access to all WaveFront commands
-* for the Tropez Plus, (primitive) control of the YSS225 FX processor
-* Virtual MIDI mode supported - 2 MIDI devices accessible via the
- WaveFront's MPU401/UART emulation. One
- accesses the WaveFront synth, the other accesses the
- external MIDI connector. Full MIDI read/write semantics
- for both devices.
-* OSS-compliant /dev/sequencer interface for the WaveFront synth,
- including native and GUS-format patch downloading.
-* semi-intelligent patch management (prototypical at this point)
-
-
-**********************************************************************
-1) What to do about MIDI interfaces ?
-**********************************************************************
-
-The Tropez Plus (and perhaps other WF cards) can in theory support up
-to 2 physical MIDI interfaces. One of these is connected to the
-ICS2115 chip (the WaveFront synth itself) and is controlled by
-MPU/UART-401 emulation code running as part of the WaveFront OS. The
-other is controlled by the CS4232 chip present on the board. However,
-physical access to the CS4232 connector is difficult, and it is
-unlikely (though not impossible) that you will want to use it.
-
-An older version of this driver introduced an additional kernel config
-variable which controlled whether or not the CS4232 MIDI interface was
-configured. Because of Alan Cox's work on modularizing the sound
-drivers, and now backporting them to 2.0.34 kernels, there seems to be
-little reason to support "static" configuration variables, and so this
-has been abandoned in favor of *only* module parameters. Specifying
-"mpuio" and "mpuirq" for the cs4232 parameter will result in the
-CS4232 MIDI interface being configured; leaving them unspecified will
-leave it unconfigured (and thus unusable).
-
-BTW, I have heard from one Tropez+ user that the CS4232 interface is
-more reliable than the ICS2115 one. I have had no problems with the
-latter, and I don't have the right cable to test the former one
-out. Reports welcome.
-
-**********************************************************************
-2) Why does line XXX of the code look like this .... ?
-**********************************************************************
-
-Either because its not finished yet, or because you're a better coder
-than I am, or because you don't understand some aspect of how the card
-or the code works.
-
-I absolutely welcome comments, criticisms and suggestions about the
-design and implementation of the driver.
-
-**********************************************************************
-3) What files are included ?
-**********************************************************************
-
- drivers/sound/README.wavefront -- this file
- drivers/sound/wavefront.patch -- patches for the 2.1.106 sound drivers
- needed to make the rest of this work
- drivers/sound/wavfront.c -- the driver
- drivers/sound/ys225.h -- data declarations for FX config
- drivers/sound/ys225.c -- data definitions for FX config
- drivers/sound/wf_midi.c -- the "uart401" driver
- to support virtual MIDI mode.
- include/wavefront.h -- the header file
- Documentation/sound/Tropez+ -- short docs on configuration
-
-**********************************************************************
-4) How do I compile/install/use it ?
-**********************************************************************
-
-PART ONE: install the source code into your sound driver directory
-
- cd <top-of-your-2.1.106-code-base-e.g.-/usr/src/linux>
- tar -zxvf <where-you-put/wavefront.tar.gz>
-
-PART TWO: apply the patches
-
- cd drivers/sound
- patch < wavefront.patch
-
-PART THREE: configure your kernel
-
- cd <top of your kernel tree>
- make xconfig (or whichever config option you use)
-
- - choose YES for Sound Support
- - choose MODULE (M) for OSS Sound Modules
- - choose MODULE(M) to YM3812/OPL3 support
- - choose MODULE(M) for WaveFront support
- - choose MODULE(M) for CS4232 support
-
- - choose "N" for everything else (unless you have other
- sound cards you want support for)
-
-
- make dep
- make boot
- .
- .
- .
- <whatever you normally do for a kernel install>
- make modules
- .
- .
- .
- make modules_install
-
-Here's my autoconf.h SOUND section:
-
-/*
- * Sound
- */
-#define CONFIG_SOUND 1
-#undef CONFIG_SOUND_OSS
-#define CONFIG_SOUND_OSS_MODULE 1
-#undef CONFIG_SOUND_PAS
-#undef CONFIG_SOUND_SB
-#undef CONFIG_SOUND_ADLIB
-#undef CONFIG_SOUND_GUS
-#undef CONFIG_SOUND_MPU401
-#undef CONFIG_SOUND_PSS
-#undef CONFIG_SOUND_MSS
-#undef CONFIG_SOUND_SSCAPE
-#undef CONFIG_SOUND_TRIX
-#undef CONFIG_SOUND_MAD16
-#undef CONFIG_SOUND_WAVEFRONT
-#define CONFIG_SOUND_WAVEFRONT_MODULE 1
-#undef CONFIG_SOUND_CS4232
-#define CONFIG_SOUND_CS4232_MODULE 1
-#undef CONFIG_SOUND_MAUI
-#undef CONFIG_SOUND_SGALAXY
-#undef CONFIG_SOUND_OPL3SA1
-#undef CONFIG_SOUND_SOFTOSS
-#undef CONFIG_SOUND_YM3812
-#define CONFIG_SOUND_YM3812_MODULE 1
-#undef CONFIG_SOUND_VMIDI
-#undef CONFIG_SOUND_UART6850
-/*
- * Additional low level sound drivers
- */
-#undef CONFIG_LOWLEVEL_SOUND
-
-************************************************************
-6) How do I configure my card ?
-************************************************************
-
-You need to edit /etc/conf.modules. Here's mine (edited to show the
-relevant details):
-
- # Sound system
- alias char-major-14 wavefront
- alias synth0 wavefront
- alias mixer0 cs4232
- alias audio0 cs4232
- pre-install wavefront modprobe "-k" "cs4232"
- post-install wavefront modprobe "-k" "opl3"
- options wavefront io=0x200 irq=9
- options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0
- options opl3 io=0x388
-
-Things to note:
-
- the wavefront options "io" and "irq" ***MUST*** match the "synthio"
- and "synthirq" cs4232 options.
-
- you can do without the adlib_card module if you don't
- want to use the OPL/[34] synth on the sound card
-
- the adlib_card io parameter is conventionally not adjustable.
- In theory, any not-in-use IO port address would work, but
- just use 0x388 and stick with the crowd.
-
-**********************************************************************
-7) What about firmware ?
-**********************************************************************
-
-Turtle Beach have not given me permission to distribute their firmware
-for the ICS2115. However, if you have a WaveFront card, then you
-almost certainly have the firmware, and if not, its freely available
-on their website, at:
-
- http://www.tbeach.com/tbs/downloads/scardsdown.htm#tropezplus
-
-The file is called WFOS2001.MOT (for the Tropez+).
-
-This driver, however, doesn't use the pure firmware as distributed,
-but instead relies on a somewhat processed form of it. You can
-generate this very easily. Following an idea from Andrew Veliath's
-Pinnacle driver, the following flex program will generate the
-processed version:
-
----- cut here -------------------------
-%option main
-%%
-^S[28].*\r$ printf ("%c%.*s", yyleng-1,yyleng-1,yytext);
-<<EOF>> { fputc ('\0', stdout); return; }
-\n {}
-. {}
----- cut here -------------------------
-
-To use it, put the above in file (say, ws.l) compile it like this:
-
- shell> flex -ows.c ws.l
- shell> cc -o ws ws.c
-
-and then use it like this:
-
- ws < my-copy-of-the-oswf.mot-file > /etc/sound/wavefront.os
-
-If you put it somewhere else, you'll always have to use the wf_ospath
-module parameter (see below) or alter the source code.
-
-**********************************************************************
-7) How do I get it working ?
-**********************************************************************
-
-Optionally, you can reboot with the "new" kernel (even though the only
-changes have really been made to a module).
-
-Then, as root do:
-
- modprobe wavefront
-
-You should get something like this in /var/log/messages:
-
- WaveFront: firmware 1.20 already loaded.
-
-or
-
- WaveFront: no response to firmware probe, assume raw.
-
-then:
-
- WaveFront: waiting for memory configuration ...
- WaveFront: hardware version 1.64
- WaveFront: available DRAM 8191k
- WaveFront: 332 samples used (266 real, 13 aliases, 53 multi), 180 empty
- WaveFront: 128 programs slots in use
- WaveFront: 256 patch slots filled, 142 in use
-
-The whole process takes about 16 seconds, the longest waits being
-after reporting the hardware version (during the firmware download),
-and after reporting program status (during patch status inquiry). Its
-shorter (about 10 secs) if the firmware is already loaded (i.e. only
-warm reboots since the last firmware load).
-
-The "available DRAM" line will vary depending on how much added RAM
-your card has. Mine has 8MB.
-
-Next, check /dev/sndstat, which on my machine says:
----------------------------------------------------------------------
-OSS/Free:3.8s2++-971130
-Load type: Driver loaded as a module
-Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486
-Config options: 0
-
-Installed drivers:
-
-Card config:
-
-Audio devices:
-0: Crystal audio controller (CS4232) (DUPLEX)
-
-Synth devices:
-0: Turtle Beach WaveFront
-1: Yamaha OPL-3
-
-Midi devices:
-0: WaveFront Internal MIDI
-1: WaveFront External MIDI
-
-Timers:
-0: System clock
-1: Crystal audio controller (CS4232)
-
-Mixers:
-0: Crystal audio controller (CS4232)
------------------------------------------------------------
-
-To check basically functionality, use play(1) or splay(1) to send a
-.WAV or other audio file through the audio portion. Then use playmidi
-to play a General MIDI file. Try the "-D 0" to hear the
-difference between sending MIDI to the WaveFront and using the OPL/3,
-which is the default (I think ...). If you have an external synth(s)
-hooked to the sound card, you can use "-e" to route to the
-external synth(s) (in theory, -D 1 should work as well, but I think
-there is a bug in playmidi which prevents this from doing what it
-should).
-
-**********************************************************************
-8) What are the module parameters ?
-**********************************************************************
-
-Its best to read wavefront.c for this, but here is a summary:
-
-integers:
- wf_raw - if set, ignore apparent presence of firmware
- loaded onto the ICS2115, reset the whole
- board, and initialize it from scratch. (default = 0)
-
- fx_raw - if set, always initialize the YSS225 processor
- on the Tropez plus. (default = 1)
-
- < The next 4 are basically for kernel hackers to allow
- tweaking the driver for testing purposes. >
-
- wf_short_wait_count - loop counter used when waiting for
- status conditions on the board. This
- is CPU-specific. After this many
- loops, the driver will sleep.
- The default is 5000. I have a 66Mhz 486.
-
- wf_sleep_interval - the driver sleeps for
- HZ/wf_sleep_interval seconds per sleep.
- The default is 50.
-
- wf_sleep_tries - the number of times the driver will sleep
- when waiting for a status condition on the
- board. The default is 100 (2 secs, if
- wf_sleep_interval is 50).
-
- wf_debug_default - debugging flags. See sound/wavefront.h
- for WF_DEBUG_* values. Default is zero.
- Setting this allows you to debug the
- driver during module installation.
-strings:
- wf_ospath - path to get to the pre-processed OS firmware.
- (default: /etc/sound/wavefront.os)
-
-**********************************************************************
-9) Who should I contact if I have problems?
-**********************************************************************
-
-Just me: Paul Barton-Davis <pbd@op.net>
-
-
diff --git a/drivers/sound/Readme b/drivers/sound/Readme
deleted file mode 100644
index cd506f29a..000000000
--- a/drivers/sound/Readme
+++ /dev/null
@@ -1,186 +0,0 @@
-OSS/Free version 3.8 release notes
-----------------------------------
-
-Most up to date information about this driver is available from
-http://www.opensound.com/ossfree.
-
-
-
-Please read the SOUND-HOWTO (available from sunsite.unc.edu and other Linux FTP
-sites). It gives instructions about using sound with Linux. It's bit out of
-date but still very useful. Information about bug fixes and such things
-is available from the web page (see above).
-
-Please check http://www.opensound.com/pguide for more info about programming
-with OSS API.
-
- ====================================================
-- THIS VERSION ____REQUIRES____ Linux 2.1.57 OR LATER.
- ====================================================
-
-Packages "snd-util-3.8.tar.gz" and "snd-data-0.1.tar.Z"
-contain useful utilities to be used with this driver.
-See http://www.opensound.com/ossfree/getting.html for
-download instructions.
-
-If you are looking for the installation instructions, please
-look at Readme.linux.
-
-Supported sound cards
----------------------
-
-See Readme.cards.
-
-Please check http://www.opensound.com/ossfree if you don't find
-your sound card there.
-
-Contributors
-------------
-
-This driver contains code by several contributors. In addition several other
-persons have given useful suggestions. The following is a list of major
-contributors. (I could have forgotten some names.)
-
- Craig Metz 1/2 of the PAS16 Mixer and PCM support
- Rob Hooft Volume computation algorithm for the FM synth.
- Mika Liljeberg uLaw encoding and decoding routines
- Jeff Tranter Linux SOUND HOWTO document
- Greg Lee Volume computation algorithm for the GUS and
- lot's of valuable suggestions.
- Andy Warner ISC port
- Jim Lowe,
- Amancio Hasty Jr FreeBSD/NetBSD port
- Anders Baekgaard Bug hunting and valuable suggestions.
- Joerg Schubert SB16 DSP support (initial version).
- Andrew Robinson Improvements to the GUS driver
- Megens SA MIDI recording for SB and SB Pro (initial version).
- Mikael Nordqvist Linear volume support for GUS and
- nonblocking /dev/sequencer.
- Ian Hartas SVR4.2 port
- Markus Aroharju and
- Risto Kankkunen Major contributions to the mixer support
- of GUS v3.7.
- Hunyue Yau Mixer support for SG NX Pro.
- Marc Hoffman PSS support (initial version).
- Rainer Vranken Initialization for Jazz16 (initial version).
- Peter Trattler Initial version of loadable module support for Linux.
- JRA Gibson 16 bit mode for Jazz16 (initial version)
- Davor Jadrijevic MAD16 support (initial version)
- Gregor Hoffleit Mozart support (initial version)
- Riccardo Facchetti Audio Excel DSP 16 (aedsp16) support
- James Hightower Spotting a tiny but important bug in CS423x support.
- Denis Sablic OPTi 82C924 spesific enhancements (non PnP mode)
- Tim MacKenzie Full duplex support for OPTi 82C930.
-
- Please look at lowlevel/README for more contributors.
-
-There are probably many other names missing. If you have sent me some
-patches and your name is not in the above list, please inform me.
-
-Sending your contributions or patches
--------------------------------------
-
-First of all it's highly recommended to contact me before sending anything
-or before even starting to do any work. Tell me what you suggest to be
-changed or what you have planned to do. Also ensure you are using the
-very latest (development) version of OSS/Free since the change may already be
-implemented there. In general it's major waste of time to try to improve
-several months old version. Information about the latest version can be found
-from http://www.opensound.com/ossfree. In general there is no point in
-sending me patches relative to production kernels.
-
-Sponsors etc.
--------------
-
-The following companies have greatly helped development of this driver
-in form of a free copy of their product:
-
-Novell, Inc. UnixWare personal edition + SDK
-The Santa Cruz Operation, Inc. A SCO OpenServer + SDK
-Ensoniq Corp, a SoundScape card and extensive amount of assistance
-MediaTrix Peripherals Inc, a AudioTrix Pro card + SDK
-Acer, Inc. a pair of AcerMagic S23 cards.
-
-In addition the following companies have provided me sufficient amount
-of technical information at least some of their products (free or $$$):
-
-Advanced Gravis Computer Technology Ltd.
-Media Vision Inc.
-Analog Devices Inc.
-Logitech Inc.
-Aztech Labs Inc.
-Crystal Semiconductor Corporation,
-Integrated Circuit Systems Inc.
-OAK Technology
-OPTi
-Turtle Beach
-miro
-Ad Lib Inc. ($$)
-Music Quest Inc. ($$)
-Creative Labs ($$$)
-
-If you have some problems
-=========================
-
-Read the sound HOWTO (sunsite.unc.edu:/pub/Linux/docs/...?).
-Also look at the home page (http://www.opensound.com/ossfree). It may
-contain info about some recent bug fixes.
-
-It's likely that you have some problems when trying to use the sound driver
-first time. Sound cards don't have standard configuration so there are no
-good default configuration to use. Please try to use same I/O, DMA and IRQ
-values for the sound card than with DOS.
-
-If you get an error message when trying to use the driver, please look
-at /var/adm/messages for more verbose error message.
-
-
-In general the easiest way to diagnose problems is to do "cat /dev/sndstat".
-
-If you get an error message, there are some problems with the driver setup:
-
- - "No such file or directory" tells that the device files for
- the sound driver are missing. Use the script at the end of
- linux/drivers/sound/Readme.linux to create them.
-
- - "No such device" tells that the sound driver is not in the kernel.
- You have to reconfigure and recompile the kernel to have the sound
- driver. Compiling the driver doesn't help alone. You have to boot
- with the newly compiled one before the driver becomes active.
- The Linux-HOWTO should help in this step.
-
-The following errors are likely with /dev/dsp and /dev/audio.
-
- - "No such device or address". This error message should not happen
- with /dev/sndstat but it's possible with the other sound devices.
- This error indicates that there are no suitable hardware for the
- device file or the sound driver has been compiled without support for
- this particular device. For example /dev/audio and /dev/dsp will not
- work if "digitized voice support" was not enabled during "make config".
-
- - "Device or resource busy". Probably the IRQ (or DMA) channel
- required by the sound card is in use by some other device/driver.
-
- - "I/O error". Almost certainly (99%) it's an IRQ or DMA conflict.
- Look at the kernel messages in /var/adm/notice for more info.
-
- - "Invalid argument". The application is calling ioctl()
- with impossible parameters. Check that the application is
- for sound driver version 2.X or later.
-
-In general the printout of /dev/sndstat should tell what is the problem.
-It's possible that there are bugs in the sound driver but 99% of the problems
-reported to me are caused by somehow incorrect setup during "make config".
-
-Best regards,
-
-Hannu
-
-Hannu Savolainen
-hannu@opensound.com
-(Please check http://www.opensound.com/ossfree before mailing me).
-
-Snail mail: Hannu Savolainen
- Hiekkalaiturintie 3 A 8
- 00980 Helsinki
- Finland
diff --git a/drivers/sound/Readme.cards b/drivers/sound/Readme.cards
deleted file mode 100644
index 45cad259e..000000000
--- a/drivers/sound/Readme.cards
+++ /dev/null
@@ -1,1227 +0,0 @@
-Configuring version 3.8 (for Linux) with some common sound cards
-================================================================
-
-This document describes configuring sound cards with the freeware version of
-Open Sound Systems (OSS/Free). Information about the commercial version
-(OSS/Linux) and its configuration is available from
-http://www.opensound.com/linux.html. Information presented here is
-not valid for OSS/Linux.
-
-If you are unsure about how to configure OSS/Free
-you can download the free evaluation version of OSS/Linux from the above
-address. There is a chance that it can autodetect your sound card. In this case
-you can use the information included in soundon.log when configuring OSS/Free.
-
-
-IMPORTANT! This document covers only cards that were "known" when
- this driver version was released. Please look at
- http://www.opensound.com/ossfree for info about
- cards introduced recently.
-
- When configuring the sound driver, you should carefully
- check each sound configuration option (particularly
- "Support for /dev/dsp and /dev/audio"). The default values
- offered by these programs are not necessarily valid.
-
-
-THE BIGGEST MISTAKES YOU CAN MAKE
-=================================
-
-1. Assuming that the card is Sound Blaster compatible when it's not.
---------------------------------------------------------------------
-
-The number one mistake is to assume that your card is compatible with
-Sound Blaster. Only the cards made by Creative Technology or which have
-one or more chips labeled by Creative are SB compatible. In addition there
-are few sound chipsets which are SB compatible in Linux such as ESS1688 or
-Jazz16. Note that SB compatibility in DOS/Windows does _NOT_ mean anything
-in Linux.
-
-IF YOU REALLY ARE 150% SURE YOU HAVE A SOUND BLASTER YOU CAN SKIP THE REST OF
-THIS CHAPTER.
-
-For most other "supposed to be SB compatible" cards you have to use other
-than SB drivers (see below). It is possible to get most sound cards to work
-in SB mode but in general it's a complete waste of time. There are several
-problems which you will encounter by using SB mode with cards that are not
-truly SB compatible:
-
-- The SB emulation is at most SB Pro (DSP version 3.x) which means that
-you get only 8 bit audio (there is always an another ("native") mode which
-gives the 16 bit capability). The 8 bit only operation is the reason why
-many users claim that sound quality in Linux is much worse than in DOS.
-In addition some applications require 16 bit mode and they produce just
-noise with a 8 bit only device.
-- The card may work only in some cases but refuse to work most of the
-time. The SB compatible mode always requires special initialization which is
-done by the DOS/Windows drivers. This kind of cards work in Linux after
-you have warm booted it after DOS but they don't work after cold boot
-(power on or reset).
-- You get the famous "DMA timed out" messages. Usually all SB clones have
-software selectable IRQ and DMA settings. If the (power on default) values
-currently used by the card don't match configuration of the driver you will
-get the above error message whenever you try to record or play. There are
-few other reasons to the DMA timeout message but using the SB mode seems
-to be the most common cause.
-
-2. Trying to use a PnP (Plug & Play) card just like an ordinary sound card
---------------------------------------------------------------------------
-
-Plug & Play is a protocol defined by Intel and Microsoft. It lets operating
-systems to easily identify and reconfigure I/O ports, IRQs and DMAs of ISA
-cards. The problem with PnP cards is that the standard Linux doesn't currently
-(versions 2.1.x and earlier) don't support PnP. This means that you will have
-to use some special tricks (see later) to get a PnP card alive. Many PnP cards
-work after they have been initialized but this is not always the case.
-
-There are sometimes both PnP and non-PnP versions of the same sound card.
-The non-PnP version is the original model which usually has been discontinued
-more than an year ago. The PnP version has the same name but with "PnP"
-appended to it (sometimes not). This causes major confusion since the non-PnP
-model works with Linux but the PnP one doesn't.
-
-You should carefully check if "Plug & Play" or "PnP" is mentioned in the name
-of the card or in the documentation or package that came with the card.
-Everything described in the rest of this document is not necessarily valid for
-PnP models of sound cards even you have managed to wake up the card properly.
-Many PnP cards are simply too different from their non-PnP ancestors which are
-covered by this document.
-
-
-Cards that are not (fully) supported by this driver
-===================================================
-
-See http://www.opensound.com/ossfree for information about sound cards
-to be supported in future.
-
-
-How to use sound without recompiling kernel and/or sound driver
-===============================================================
-
-There is a commercial sound driver which comes in precompiled form and doesn't
-require recompiling of the kernel. See http://www.4Front-tech.com/oss.html for
-more info.
-
-
-Configuring PnP cards
-=====================
-
-New versions of most sound cards use the so-called ISA PnP protocol for
-soft configuring their I/O, IRQ, DMA and shared memory resources.
-Currently at least cards made by Creative Technology (SB32 and SB32AWE
-PnP), Gravis (GUS PnP and GUS PnP Pro), Ensoniq (Soundscape PnP) and
-Aztech (some Sound Galaxy models) use PnP technology. The CS4232/4236 audio
-chip by Crystal Semiconductor (Intel Atlantis, HP Pavilion and many other
-motherboards) is also based on PnP technology but there is a "native" driver
-available for it (see information about CS4232 later in this document).
-
-PnP sound cards (as well as most other PnP ISA cards) are not supported
-by this version of the driver . Proper
-support for them should be released during 97 once the kernel level
-PnP support is available.
-
-There is a method to get most of the PnP cards to work. The basic method
-is the following:
-
-1) Boot DOS so the card's DOS drivers have a chance to initialize it.
-2) _Cold_ boot to Linux by using "loadlin.exe". Hitting ctrl-alt-del
-works with older machines but causes a hard reset of all cards on recent
-(Pentium) machines.
-3) If you have the sound driver in Linux configured properly, the card should
-work now. "Proper" means that I/O, IRQ and DMA settings are the same as in
-DOS. The hard part is to find which settings were used. See the documentation of
-your card for more info.
-
-Windows 95 could work as well as DOS but running loadlin may be difficult.
-Probably you should "shut down" your machine to MS-DOS mode before running it.
-
-Some machines have a BIOS utility for setting PnP resources. This is a good
-way to configure some cards. In this case you don't need to boot DOS/Win95
-before starting Linux.
-
-Another way to initialize PnP cards without DOS/Win95 is a Linux based
-PnP isolation tool. When writing this there is a pre alpha test version
-of such a tool available from ftp://ftp.demon.co.uk/pub/unix/linux/utils. The
-file is called isapnptools-*. Please note that this tool is just a temporary
-solution which may be incompatible with future kernel versions having proper
-support for PnP cards. There are bugs in setting DMA channels in earlier
-versions of isapnptools so at least version 1.6 is required with sound cards.
-
-Yet another way to use PnP cards is to use (commercial) OSS/Linux drivers. See
-http://www.opensound.com/linux.html for more info. This is probably the way you
-should do it if you don't want to spend time recompiling the kernel and
-required tools.
-
-
-Read this before trying to configure the driver
-===============================================
-
-There are currently many cards that work with this driver. Some of the cards
-have native support while others work since they emulate some other
-card (usually SB, MSS/WSS and/or MPU401). The following cards have native
-support in the driver. Detailed instructions for configuring these cards
-will be given later in this document.
-
-Pro Audio Spectrum 16 (PAS16) and compatibles:
- Pro Audio Spectrum 16
- Pro Audio Studio 16
- Logitech Sound Man 16
- NOTE! The original Pro Audio Spectrum as well as the PAS+ are not
- and will not be supported by the driver.
-
-Media Vision Jazz16 based cards
- Pro Sonic 16
- Logitech SoundMan Wave
- (Other Jazz based cards should work but I don't have any reports
- about them).
-
-Sound Blasters
- SB 1.0 to 2.0
- SB Pro
- SB 16
- SB32/64/AWE
- Configure SB32/64/AWE just like SB16. See lowlevel/README.awe
- for information about using the wave table synth.
- NOTE! AWE63/Gold and 16/32/AWE "PnP" cards need to be activated
- using isapnptools before they work with OSS/Free.
- SB16 compatible cards by other manufacturers than Creative.
- You have been fooled since there are _no_ SB16 compatible
- cards on the market (as of May 1997). It's likely that your card
- is compatible just with SB Pro but there is also a non-SB-
- compatible 16 bit mode. Usually it's MSS/WSS but it could also
- be a proprietary one like MV Jazz16 or ESS ES688. OPTi
- MAD16 chips are very common in so called "SB 16 bit cards"
- (try with the MAD16 driver).
-
- ======================================================================
- "Supposed to be SB compatible" cards.
- Forget the SB compatibility and check for other alternatives
- first. The only cards that work with the SB driver in
- Linux have been made by Creative Technology (there is at least
- one chip on the card with "CREATIVE" printed on it). The
- only other SB compatible chips are ESS and Jazz16 chips
- (maybe ALSxxx chips too but they probably don't work).
- Most other "16 bit SB compatible" cards such as "OPTi/MAD16" or
- "Crystal" are _NOT_ SB compatible in Linux.
-
- Practically all sound cards have some kind of SB emulation mode
- in addition to their native (16 bit) mode. In most cases this
- (8 bit only) SB compatible mode doesn't work with Linux. If
- you get it working it may cause problems with games and
- applications which require 16 bit audio. Some 16 bit only
- applications don't check if the card actually supports 16 bits.
- They just dump 16 bit data to a 8 bit card which produces just
- noise.
-
- In most cases the 16 bit native mode is supported by Linux.
- Use the SB mode with "clones" only if you don't find anything
- better from the rest of this doc.
- ======================================================================
-
-Gravis Ultrasound (GUS)
- GUS
- GUS + the 16 bit option
- GUS MAX
- GUS ACE (No MIDI port and audio recording)
- GUS PnP (with RAM)
-
-MPU-401 and compatibles
- The driver works both with the full (intelligent mode) MPU-401
- cards (such as MPU IPC-T and MQX-32M) and with the UART only
- dumb MIDI ports. MPU-401 is currently the most common MIDI
- interface. Most sound cards are compatible with it. However,
- don't enable MPU401 mode blindly. Many cards with native support
- in the driver have their own MPU401 driver. Enabling the standard one
- will cause a conflict with these cards. So check if your card is
- in the list of supported cards before enabling MPU401.
-
-Windows Sound System (MSS/WSS)
- Even when Microsoft has discontinued their own Sound System card
- they managed to make it a standard. MSS compatible cards are based on
- a codec chip which is easily available from at least two manufacturers
- (AD1848 by Analog Devices and CS4231/CS4248 by Crystal Semiconductor).
- Currently most sound cards are based on one of the MSS compatible codec
- chips. The CS4231 is used in the high quality cards such as GUS MAX,
- MediaTrix AudioTrix Pro and TB Tropez (GUS MAX is not MSS compatible).
-
- Having a AD1848, CS4248 or CS4231 codec chip on the card is a good
- sign. Even if the card is not MSS compatible, it could be easy to write
- support for it. Note also that most MSS compatible cards
- require special boot time initialization which may not be present
- in the driver. Also, some MSS compatible cards have native support.
- Enabling the MSS support with these cards is likely to
- cause a conflict. So check if your card is listed in this file before
- enabling the MSS support.
-
-Yamaha FM synthesizers (OPL2, OPL3 (not OPL3-SA) and OPL4)
- Most sound cards have a FM synthesizer chip. The OPL2 is a 2
- operator chip used in the original AdLib card. Currently it's used
- only in the cheapest (8 bit mono) cards. The OPL3 is a 4 operator
- FM chip which provides better sound quality and/or more available
- voices than the OPL2. The OPL4 is a new chip that has an OPL3 and
- a wave table synthesizer packed onto the same chip. The driver supports
- just the OPL3 mode directly. Most cards with an OPL4 (like
- SM Wave and AudioTrix Pro) support the OPL4 mode using MPU401
- emulation. Writing a native OPL4 support is difficult
- since Yamaha doesn't give information about their sample ROM chip.
-
- Enable the generic OPL2/OPL3 FM synthesizer support if your
- card has a FM chip made by Yamaha. Don't enable it if your card
- has a software (TRS) based FM emulator.
-
- ----------------------------------------------------------------
- NOTE! OPL3-SA is different chip than the ordinary OPL3. In addition
- to the FM synth this chip has also digital audio (WSS) and
- MIDI (MPU401) capabilities. Support for OPL3-SA is described below.
- ----------------------------------------------------------------
-
-Yamaha OPL3-SA1
-
- Yamaha OPL3-SA1 (YMF701) is an audio controller chip used on some
- (Intel) motherboards and on cheap sound cards. It should not be
- confused with the original OPL3 chip (YMF278) which is entirely
- different chip. OPL3-SA1 has support for MSS, MPU401 and SB Pro
- (not used in OSS/Free) in addition to the OPL3 FM synth.
-
- There are also chips called OPL3-SA2, OPL3-SA3, ..., OPL3SA-N. They
- are PnP chips and will not work with the OPL3-SA1 driver. You should
- use the standard MSS, MPU401 and OPL3 options with thses chips and to
- activate the card using isapnptools.
-
-4Front Technologies SoftOSS
-
- SoftOSS is a software based wave table emulation which works with
- any 16 bit stereo sound card. Due to its nature a fast CPU is
- required (P133 is minimum). Although SoftOSS does _not_ use MMX
- instructions it has proven out that recent processors (which appear
- to have MMX) perform significantly better with SoftOSS than earlier
- ones. For example a P166MMX beats a PPro200. SoftOSS should not be used
- on 486 or 386 machines.
-
- The amount of CPU load caused by SoftOSS can be controlled by
- selecting the CONFIG_SOFTOSS_RATE and CONFIG_SOFTOSS_VOICES
- parameters properly (they will be prompted by make config). It's
- recommended to set CONFIG_SOFTOSS_VOICES to 32. If you have a
- P166MMX or faster (PPro200 is not faster) you can set
- CONFIG_SOFTOSS_RATE to 44100 (kHz). However with slower systems it
- recommended to use sampling rates around 22050 or even 16000 kHz.
- Selecting too high values for these parameters may hang your
- system when playing MIDI files with hight degree of polyphony
- (number of concurrently playing notes). It's also possible to
- decrease CONFIG_SOFTOSS_VOICES. This makes it possible to use
- higher sampling rates. However using fewer voices decreases
- playback quality more than decreasing the sampling rate.
-
- SoftOSS keeps the samples loaded on the system's RAM so much RAM is
- required. SoftOSS should never be used on machines with less than 16 MB
- of RAM since this is potentially dangerous (you may accidently run out
- of memory which probably crashes the machine).
-
- SoftOSS implements the wave table API originally designed for GUS. For
- this reason all applications designed for GUS should work (at least
- after minor modifications). For example gmod/xgmod and playmidi -g are
- known to work.
-
- To work SoftOSS will require GUS compatible
- patch files to be installed on the system (in /dos/ultrasnd/midi). You
- can use the public domain MIDIA patchset available from several ftp
- sites.
-
- *********************************************************************
- IMPORTANT NOTICE! The original patch set distributed with the Gravis
- Ultrasound card is not in public domain (even though it's available from
- some FTP sites). You should contact Voice Crystal (www.voicecrystal.com)
- if you like to use these patches with SoftOSS included in OSS/Free.
- *********************************************************************
-
-PSS based cards (AD1848 + ADSP-2115 + Echo ESC614 ASIC)
- Analog Devices and Echo Speech have together defined a sound card
- architecture based on the above chips. The DSP chip is used
- for emulation of SB Pro, FM and General MIDI/MT32.
-
- There are several cards based on this architecture. The most known
- ones are Orchid SW32 and Cardinal DSP16.
-
- The driver supports downloading DSP algorithms to these cards.
-
- NOTE! You will have to use the "old" config script when configuring
- PSS cards.
-
-MediaTrix AudioTrix Pro
- The ATP card is built around a CS4231 codec and an OPL4 synthesizer
- chips. The OPL4 mode is supported by a microcontroller running a
- General MIDI emulator. There is also a SB 1.5 compatible playback mode.
-
-Ensoniq SoundScape and compatibles
- Ensoniq has designed a sound card architecture based on the
- OTTO synthesizer chip used in their professional MIDI synthesizers.
- Several companies (including Ensoniq, Reveal and Spea) are selling
- cards based on this architecture.
-
- NOTE! The SoundScape PnP is not supported by OSS/Free. Ensoniq VIVO and
- VIVO90 cards are not compatible with Soundscapes so the Soundscape
- driver will not work with them. You may want to use OSS/Linux with these
- cards.
-
-OPTi MAD16 and Mozart based cards
- The Mozart (OAK OTI-601), MAD16 (OPTi 82C928), MAD16 Pro (OPTi 82C929),
- OPTi 82C924/82C925 (in _non_ PnP mode) and OPTi 82C930 interface
- chips are used in many different sound cards, including some
- cards by Reveal miro and Turtle Beach (Tropez). The purpose of these
- chips is to connect other audio components to the PC bus. The
- interface chip performs address decoding for the other chips.
- NOTE! Tropez Plus is not MAD16 but CS4232 based.
- NOTE! MAD16 PnP cards (82C924, 82C925, 82C931) are not MAD16 compatible
- in the PnP mode. You will have to use them in MSS mode after having
- initialized them using isapnptools or DOS. 82C931 probably requires
- initialization using DOS/Windows (running isapnptools is not enough).
- It's possible to use 82C931 with OSS/Free by jumpering it to non-PnP
- mode (provided that the card has a jumper for this). In non-PnP mode
- 82C931 is compatible with 82C930 and should work with the MAD16 driver
- (without need to use isapnptools or DOS to initialize it). All OPTi
- chips are supported by OSS/Linux (both in PnP and non-PnP modes).
-
-Audio Excel DSP16
- Support for this card was written by Riccardo Faccetti
- (riccardo@cdc8g5.cdc.polimi.it). The AEDSP16 driver included in
- the lowlevel/ directory. To use it you should enable the
- "Additional low level drivers" option.
-
-Crystal CS4232 and CS4236 based cards such as AcerMagic S23, TB Tropez _Plus_ and
- many PC motherboards (Compaq, HP, Intel, ...)
- CS4232 is a PnP multimedia chip which contains a CS3231A codec,
- SB and MPU401 emulations. There is support for OPL3 too.
- Unfortunately the MPU401 mode doesn't work (I don't know how to
- initialize it). CS4236 is an enhanced (compatible) version of CS4232.
- NOTE! Don't ever try to use isapnptools with CS4232 since this will just
- freeze your machine (due to chip bugs). If you have problems in getting
- CS4232 working you could try initializing it with DOS (CS4232C.EXE) and
- then booting Linux using loadlin. CS4232C.EXE loads a secret firmware
- patch which is not documented by Crystal.
-
-Turtle Beach Maui and Tropez "classic"
- This driver version supports sample, patch and program loading commands
- described in the Maui/Tropez User's manual.
- There is now full initialization support too. The audio side of
- the Tropez is based on the MAD16 chip (see above).
- NOTE! Tropez Plus is different card than Tropez "classic" and will not
- work fully in Linux. You can get audio features working by configuring
- the card as a CS4232 based card (above).
-
-
-Jumpers and software configuration
-==================================
-
-Some of the earliest sound cards were jumper configurable. You have to
-configure the driver use I/O, IRQ and DMA settings
-that match the jumpers. Just few 8 bit cards are fully jumper
-configurable (SB 1.x/2.x, SB Pro and clones).
-Some cards made by Aztech have an EEPROM which contains the
-config info. These cards behave much like hardware jumpered cards.
-
-Most cards have jumper for the base I/O address but other parameters
-are software configurable. Sometimes there are few other jumpers too.
-
-Latest cards are fully software configurable or they are PnP ISA
-compatible. There are no jumpers on the board.
-
-The driver handles software configurable cards automatically. Just configure
-the driver to use I/O, IRQ and DMA settings which are known to work.
-You could usually use the same values than with DOS and/or Windows.
-Using different settings is possible but not recommended since it may cause
-some trouble (for example when warm booting from an OS to another or
-when installing new hardware to the machine).
-
-Sound driver sets the soft configurable parameters of the card automatically
-during boot. Usually you don't need to run any extra initialization
-programs when booting Linux but there are some exceptions. See the
-card-specific instructions below for more info.
-
-The drawback of software configuration is that the driver needs to know
-how the card must be initialized. It cannot initialize unknown cards
-even if they are otherwise compatible with some other cards (like SB,
-MPU401 or Windows Sound System).
-
-
-What if your card was not listed above?
-=======================================
-
-The first thing to do is to look at the major IC chips on the card.
-Many of the latest sound cards are based on some standard chips. If you
-are lucky, all of them could be supported by the driver. The most common ones
-are the OPTi MAD16, Mozart, SoundScape (Ensoniq) and the PSS architectures
-listed above. Also look at the end of this file for list of unsupported
-cards and the ones which could be supported later.
-
-The last resort is to send _exact_ name and model information of the card
-to me together with a list of the major IC chips (manufactured, model) to
-me. I could then try to check if your card looks like something familiar.
-
-There are many more cards in the world than listed above. The first thing to
-do with these cards is to check if they emulate some other card or interface
-such as SB, MSS and/or MPU401. In this case there is a chance to get the
-card to work by booting DOS before starting Linux (boot DOS, hit ctrl-alt-del
-and boot Linux without hard resetting the machine). In this method the
-DOS based driver initializes the hardware to use known I/O, IRQ and DMA
-settings. If sound driver is configured to use the same settings, everything
-should work OK.
-
-
-Configuring sound driver (with Linux)
-=====================================
-
-The sound driver is currently distributed as part of the Linux kernel. The
-files are in /usr/src/linux/drivers/sound/.
-
-****************************************************************************
-* ALWAYS USE THE SOUND DRIVER VERSION WHICH IS DISTRIBUTED WITH *
-* THE KERNEL SOURCE PACKAGE YOU ARE USING. SOME ALPHA AND BETA TEST *
-* VERSIONS CAN BE INSTALLED FROM A SEPARATELY DISTRIBUTED PACKAGE *
-* BUT CHECK THAT THE PACKAGE IS NOT MUCH OLDER (OR NEWER) THAN THE *
-* KERNEL YOU ARE USING. IT'S POSSIBLE THAT THE KERNEL/DRIVER *
-* INTERFACE CHANGES BETWEEN KERNEL RELEASES WHICH MAY CAUSE SOME *
-* INCOMPATIBILITY PROBLEMS. *
-* *
-* IN CASE YOU INSTALL A SEPARATELY DISTRIBUTED SOUND DRIVER VERSION, *
-* BE SURE TO REMOVE OR RENAME THE OLD SOUND DRIVER DIRECTORY BEFORE *
-* INSTALLING THE NEW ONE. LEAVING OLD FILES TO THE SOUND DRIVER *
-* DIRECTORY _WILL_ CAUSE PROBLEMS WHEN THE DRIVER IS USED OR *
-* COMPILED. *
-****************************************************************************
-
-To configure the driver, run "make config" in the kernel source directory
-(/usr/src/linux). Answer "y" or "m" to the question about Sound card support
-(after the questions about mouse, CD-ROM, ftape, etc. support). Questions
-about options for sound will then be asked.
-
-After configuring the kernel and sound driver, run "make dep" and compile
-the kernel following instructions in the kernel README.
-
-The sound driver configuration dialog
--------------------------------------
-
-If you already have the sound driver installed, consult a printout of
-"cat /dev/sndstat" when configuring the driver again. It gives the I/O,
-IRQ and DMA settings you used earlier.
-
-Sound configuration starts by making some yes/no questions. Be careful
-when answering to these questions since answering y to a question may
-prevent some later ones from being asked. For example don't answer y to
-the first question (PAS16) if you don't really have a PAS16. Don't enable
-more cards than you really need since they just consume memory. Also
-some drivers (like MPU401) may conflict with your SCSI controller and
-prevent kernel from booting. If you card was in the list of supported
-cards (above), please look at the card specific config instructions
-(later in this file) before starting to configure. Some cards must be
-configured in way which is not obvious.
-
-So here is the beginning of the config dialog. Answer 'y' or 'n' to these
-questions. The default answer is shown so that (y/n) means 'y' by default and
-(n/y) means 'n'. To use the default value, just hit ENTER. But be careful
-since using the default _doesn't_ guarantee anything.
-
-Note also that all questions may not be asked. The configuration program
-may disable some questions depending on the earlier choices. It may also
-select some options automatically as well.
-
- "ProAudioSpectrum 16 support",
- - Answer 'y'_ONLY_ if you have a Pro Audio Spectrum _16_,
- Pro Audio Studio 16 or Logitech SoundMan 16 (be sure that
- you read the above list correctly). Don't answer 'y' if you
- have some other card made by Media Vision or Logitech since they
- are not PAS16 compatible.
- NOTE! Since 3.5-beta10 you need to enable SB support (next question)
- if you want to use the SB emulation of PAS16. It's also possible to
- the emulation if you want to use a true SB card together with PAS16
- (there is another question about this that is asked later).
- "Sound Blaster support",
- - Answer 'y' if you have an original SB card made by Creative Labs
- or a full 100% hardware compatible clone (like Thunderboard or
- SM Games). If your card was in the list of supported cards (above),
- please look at the card specific instructions later in this file
- before answering this question. For an unknown card you may answer
- 'y' if the card claims to be SB compatible.
- Enable this option also with PAS16 (changed since v3.5-beta9).
-
- Don't enable SB if you have a MAD16 or Mozart compatible card.
-
- "Generic OPL2/OPL3 FM synthesizer support",
- - Answer 'y' if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
- Answering 'y' is usually a safe and recommended choice. However some
- cards may have software (TSR) FM emulation. Enabling FM support
- with these cards may cause trouble. However I don't currently know
- such cards.
- "Gravis Ultrasound support",
- - Answer 'y' if you have GUS or GUS MAX. Answer 'n' if you don't
- have GUS since the GUS driver consumes much memory.
- Currently I don't have experiences with the GUS ACE so I don't
- know what to answer with it.
- "MPU-401 support (NOT for SB16)",
- - Be careful with this question. The MPU401 interface is supported
- by almost any sound card today. However some natively supported cards
- have their own driver for MPU401. Enabling the MPU401 option with
- these cards will cause a conflict. Also enabling MPU401 on a system
- that doesn't really have a MPU401 could cause some trouble. If your
- card was in the list of supported cards (above), please look at
- the card specific instructions later in this file.
-
- In MOST cases this MPU401 driver should only be used with "true"
- MIDI-only MPU401 professional cards. In most other cases there
- is another way to get the MPU401 compatible interface of a
- sound card to work.
- Support for the MPU401 compatible MIDI port of SB16, ESS1688
- and MV Jazz16 cards is included in the SB driver. Use it instead
- of this separate MPU401 driver with these cards. As well
- Soundscape, PSS and Maui drivers include their own MPU401
- options.
-
- It's safe to answer 'y' if you have a true MPU401 MIDI interface
- card.
- "6850 UART Midi support",
- - It's safe to answer 'n' to this question in all cases. The 6850
- UART interface is so rarely used.
- "PSS (ECHO-ADI2111) support",
- - Answer 'y' only if you have Orchid SW32, Cardinal DSP16 or some
- other card based on the PSS chipset (AD1848 codec + ADSP-2115
- DSP chip + Echo ESC614 ASIC CHIP).
- "16 bit sampling option of GUS (_NOT_ GUS MAX)",
- - Answer 'y' if you have installed the 16 bit sampling daughtercard
- to your GUS. Answer 'n' if you have GUS MAX. Enabling this option
- disables GUS MAX support.
- "GUS MAX support",
- - Answer 'y' only if you have a GUS MAX.
- "Microsoft Sound System support",
- - Again think carefully before answering 'y' to this question. It's
- safe to answer 'y' in case you have the original Windows Sound
- System card made by Microsoft or Aztech SG 16 Pro (or NX16 Pro).
- Also you may answer 'y' in case your card was not listed earlier
- in this file. For cards having native support in the driver, consult
- the card specific instructions later in this file. Some drivers
- have their own MSS support and enabling this option will cause a
- conflict.
- Note! The MSS driver permits configuring two DMA channels. This is a
- "nonstandard" feature and works only with very few cards (if any).
- In most cases the second DMA channel should be disabled or set to
- the same channel than the first one. Trying to configure two separate
- channels with cards that don't support this feature will prevent
- audio (at least recording) from working.
- "Ensoniq Soundscape support",
- - Answer 'y' if you have a sound card based on the Ensoniq SoundScape
- chipset. Such cards are being manufactured at least by Ensoniq,
- Spea and Reveal (note that Reveal makes other cards also). The oldest
- cards made by Spea don't work properly with Linux.
- Soundscape PnP as well as Ensoniq VIVO work only with the commercial
- OSS/Linux version.
- "MediaTrix AudioTrix Pro support",
- - Answer 'y' if you have the AudioTrix Pro.
- "Support for MAD16 and/or Mozart based cards",
- - Answer y if your card has a Mozart (OAK OTI-601) or MAD16
- (OPTi 82C928, 82C929, 82C924/82C925 or 82C930) audio interface chip.
- These chips are
- currently quite common so it's possible that many no-name cards
- have one of them. In addition the MAD16 chip is used in some
- cards made by known manufacturers such as Turtle Beach (Tropez),
- Reveal (some models) and Diamond (some recent models).
- Note OPTi 82C924 and 82C925 are MAD16 compatible only in non PnP
- mode (jumper selectable on many cards).
- "Support for TB Maui"
- - This enables TB Maui specific initialization. Works with TB Maui
- and TB Tropez (may not work with Tropez Plus).
-
-
-Then the configuration program asks some y/n questions about the higher
-level services. It's recommended to answer 'y' to each of these questions.
-Answer 'n' only if you know you will not need the option.
-
- "MIDI interface support",
- - Answering 'n' disables /dev/midi## devices and access to any
- MIDI ports using /dev/sequencer and /dev/music. This option
- also affects any MPU401 and/or General MIDI compatible devices.
- "FM synthesizer (YM3812/OPL-3) support",
- - Answer 'y' here.
- "/dev/sequencer support",
- - Answering 'n' disables /dev/sequencer and /dev/music.
-
-Entering the I/O, IRQ and DMA config parameters
------------------------------------------------
-
-After the above questions the configuration program prompts for the
-card specific configuration information. Usually just a set of
-I/O address, IRQ and DMA numbers are asked. With some cards the program
-asks for some files to be used during initialization of the card. For example
-many cards have a DSP chip or microprocessor which must be initialized by
-downloading a program (microcode) file to the card.
-
-Instructions for answering these questions are given in the next section.
-
-
-Card specific information
-=========================
-
-This section gives additional instructions about configuring some cards.
-Please refer manual of your card for valid I/O, IRQ and DMA numbers. Using
-the same settings with DOS/Windows and Linux is recommended. Using
-different values could cause some problems when switching between
-different operating systems.
-
-Sound Blasters (the original ones by Creative)
----------------------------------------------
-
-NOTE! Check if you have a PnP Sound Blaster (cards sold after summer 1995
- are almost certainly PnP ones). With PnP cards you should use isapnptools
- to activate them (see above).
-
-It's possible to configure these cards to use different I/O, IRQ and
-DMA settings. Since the possible/default settings have changed between various
-models, you have to consult manual of your card for the proper ones. It's
-a good idea to use the same values than with DOS/Windows. With SB and SB Pro
-it's the only choice. SB16 has software selectable IRQ and DMA channels but
-using different values with DOS and Linux is likely to cause troubles. The
-DOS driver is not able to reset the card properly after warm boot from Linux
-if Linux has used different IRQ or DMA values.
-
-The original (steam) Sound Blaster (versions 1.x and 2.x) use always
-DMA1. There is no way to change it.
-
-The SB16 needs two DMA channels. A 8 bit one (1 or 3) is required for
-8 bit operation and a 16 bit one (5, 6 or 7) for the 16 bit mode. In theory
-it's possible to use just one (8 bit) DMA channel by answering the 8 bit
-one when the configuration program asks for the 16 bit one. This may work
-in some systems but is likely to cause terrible noise on some other systems.
-
-It's possible to use two SB16/32/64 at the same time. To do this you should
-first configure OSS/Free for one card. Then edit local.h manually and define
-SB2_BASE, SB2_IRQ, SB2_DMA and SB2_DMA2 for the second one. You can't get
-the OPL3, MIDI and EMU8000 devices of the second card to work. If you are
-going to use two PnP Sound Blasters, ensure that they are of different model
-and have different PnP IDs. There is no way to get two cards with the same
-card ID and serial number to work. The easiest way to check this is trying
-if isapnptools can see both cards or just one.
-
-NOTE! Don't enable the SM Games option (asked by the configuration program)
- if you are not 101% sure that your card is a Logitech Soundman Games
- (not a SM Wave or SM16).
-
-SB Clones
----------
-
-First of all: There are no SB16 clones. There are SB Pro clones with a
-16 bit mode which is not SB16 compatible. The most likely alternative is that
-the 16 bit mode means MSS/WSS.
-
-There are just a few fully 100% hardware SB or SB Pro compatible cards.
-I know just Thunderboard and SM Games. Other cards require some kind of
-hardware initialization before they become SB compatible. Check if your card
-was listed in the beginning of this file. In this case you should follow
-instructions for your card later in this file.
-
-For other not fully SB clones you may try initialization using DOS in
-the following way:
-
- - Boot DOS so that the card specific driver gets run.
- - Hit ctrl-alt-del (or use loadlin) to boot Linux. Don't
- switch off power or press the reset button.
- - If you use the same I/O, IRQ and DMA settings in Linux, the
- card should work.
-
-If your card is both SB and MSS compatible, I recommend using the MSS mode.
-Most cards of this kind are not able to work in the SB and the MSS mode
-simultaneously. Using the MSS mode provides 16 bit recording and playback.
-
-ProAudioSpectrum 16 and compatibles
------------------------------------
-
-PAS16 has a SB emulation chip which can be used together with the native
-(16 bit) mode of the card. To enable this emulation you should configure
-the driver to have SB support too (this has been changed since version
-3.5-beta9 of this driver).
-
-With current driver versions it's also possible to use PAS16 together with
-another SB compatible card. In this case you should configure SB support
-for the other card and to disable the SB emulation of PAS16 (there is a
-separate questions about this).
-
-With PAS16 you can use two audio device files at the same time. /dev/dsp (and
-/dev/audio) is connected to the 8/16 bit native codec and the /dev/dsp1 (and
-/dev/audio1) is connected to the SB emulation (8 bit mono only).
-
-Gravis Ultrasound
------------------
-
-There are many different revisions of the Ultrasound card (GUS). The
-earliest ones (pre 3.7) don't have a hardware mixer. With these cards
-the driver uses a software emulation for synth and pcm playbacks. It's
-also possible to switch some of the inputs (line in, mic) off by setting
-mixer volume of the channel level below 10%. For recording you have
-to select the channel as a recording source and to use volume above 10%.
-
-GUS 3.7 has a hardware mixer.
-
-GUS MAX and the 16 bit sampling daughtercard have a CS4231 codec chip which
-also contains a mixer.
-
-Configuring GUS is simple. Just enable the GUS support and GUS MAX or
-the 16 bit daughtercard if you have them. Note that enabling the daughter
-card disables GUS MAX driver.
-
-NOTE for owners of the 16 bit daughtercard: By default the daughtercard
-uses /dev/dsp (and /dev/audio). Command "ln -sf /dev/dsp1 /dev/dsp"
-selects the daughter card as the default device.
-
-With just the standard GUS enabled the configuration program prompts
-for the I/O, IRQ and DMA numbers for the card. Use the same values than
-with DOS.
-
-With the daughter card option enabled you will be prompted for the I/O,
-IRQ and DMA numbers for the daughter card. You have to use different I/O
-and DMA values than for the standard GUS. The daughter card permits
-simultaneous recording and playback. Use /dev/dsp (the daughtercard) for
-recording and /dev/dsp1 (GUS GF1) for playback.
-
-GUS MAX uses the same I/O address and IRQ settings than the original GUS
-(GUS MAX = GUS + a CS4231 codec). In addition an extra DMA channel may be used.
-Using two DMA channels permits simultaneous playback using two devices
-(dev/dsp0 and /dev/dsp1). The second DMA channel is required for
-full duplex audio.
-To enable the second DMA channels, give a valid DMA channel when the config
-program asks for the GUS MAX DMA (entering -1 disables the second DMA).
-Using 16 bit DMA channels (5,6 or 7) is recommended.
-
-If you have problems in recording with GUS MAX, you could try to use
-just one 8 bit DMA channel. Recording will not work with one DMA
-channel if it's a 16 bit one.
-
-Microphone input of GUS MAX is connected to mixer in little bit nonstandard
-way. There is actually two microphone volume controls. Normal "mic" controls
-only recording level. Mixer control "speaker" is used to control volume of
-microphone signal connected directly to line/speaker out. So just decrease
-volume of "speaker" if you have problems with microphone feedback.
-
-GUS ACE works too but any attempt to record or to use the MIDI port
-will fail.
-
-GUS PnP (with RAM) is partially supported but it needs to be initialized using
-DOS or isapnptools before starting the driver.
-
-MPU401 and Windows Sound System
--------------------------------
-
-Again. Don't enable these options in case your card is listed
-somewhere else in this file.
-
-Configuring these cards is obvious (or it should be). With MSS
-you should probably enable the OPL3 synth also since
-most MSS compatible cards have it. However check that this is true
-before enabling OPL3.
-
-Sound driver supports more than one MPU401 compatible cards at the same time
-but the config program asks config info for just the first of them.
-Adding the second or third MPU interfaces must be done manually by
-editing sound/local.h (after running the config program). Add defines for
-MPU2_BASE & MPU2_IRQ (and MPU3_BASE & MPU3_IRQ) to the file.
-
-CAUTION!
-
-The default I/O base of Adaptec AHA-1542 SCSI controller is 0x330 which
-is also the default of the MPU401 driver. Don't configure the sound driver to
-use 0x330 as the MPU401 base if you have a AHA1542. The kernel will not boot
-if you make this mistake.
-
-PSS
----
-
-Even the PSS cards are compatible with SB, MSS and MPU401, you must not
-enable these options when configuring the driver. The configuration
-program handles these options itself. (You may use the SB, MPU and MSS options
-together with PSS if you have another card on the system).
-
-The PSS driver enables MSS and MPU401 modes of the card. SB is not enabled
-since it doesn't work concurrently with MSS. The driver loads also a
-DSP algorithm which is used to for the general MIDI emulation. The
-algorithm file (.ld) is read by the config program and written to a
-file included when the pss.c is compiled. For this reason the config
-program asks if you want to download the file. Use the genmidi.ld file
-distributed with the DOS/Windows drivers of the card (don't use the mt32.ld).
-With some cards the file is called 'synth.ld'. You must have access to
-the file when configuring the driver. The easiest way is to mount the DOS
-partition containing the file with Linux.
-
-It's possible to load your own DSP algorithms and run them with the card.
-Look at the directory pss_test of snd-util-3.0.tar.gz for more info.
-
-AudioTrix Pro
--------------
-
-You have to enable the OPL3 and SB (not SB Pro or SB16) drivers in addition
-to the native AudioTrix driver. Don't enable MSS or MPU drivers.
-
-Configuring ATP is little bit tricky since it uses so many I/O, IRQ and
-DMA numbers. Using the same values than with DOS/Win is a good idea. Don't
-attempt to use the same IRQ or DMA channels twice.
-
-The SB mode of ATP is implemented so the ATP driver just enables SB
-in the proper address. The SB driver handles the rest. You have to configure
-both the SB driver and the SB mode of ATP to use the same IRQ, DMA and I/O
-settings.
-
-Also the ATP has a microcontroller for the General MIDI emulation (OPL4).
-For this reason the driver asks for the name of a file containing the
-microcode (TRXPRO.HEX). This file is usually located in the directory
-where the DOS drivers were installed. You must have access to this file
-when configuring the driver.
-
-If you have the effects daughtercard, it must be initialized by running
-the setfx program of snd-util-3.0.tar.gz package. This step is not required
-when using the (future) binary distribution version of the driver.
-
-Ensoniq SoundScape
-------------------
-
-NOTE! The new PnP SoundScape is not supported yet. Soundscape compatible
- cards made by Reveal don't work with Linux. They use older revision
- of the Soundscape chipset which is not fully compatible with
- newer cards made by Ensoniq.
-
-The SoundScape driver handles initialization of MSS and MPU supports
-itself so you don't need to enable other drivers than SoundScape
-(enable also the /dev/dsp, /dev/sequencer and MIDI supports).
-
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!!!!! !!!!
-!!!!! NOTE! Before version 3.5-beta6 there WERE two sets of audio !!!!
-!!!!! device files (/dev/dsp0 and /dev/dsp1). The first one WAS !!!!
-!!!!! used only for card initialization and the second for audio !!!!
-!!!!! purposes. It WAS required to change /dev/dsp (a symlink) to !!!!
-!!!!! point to /dev/dsp1. !!!!
-!!!!! !!!!
-!!!!! This is not required with OSS versions 3.5-beta6 and later !!!!
-!!!!! since there is now just one audio device file. Please !!!!
-!!!!! change /dev/dsp to point back to /dev/dsp0 if you are !!!!
-!!!!! upgrading from an earlier driver version using !!!!
-!!!!! (cd /dev;rm dsp;ln -s dsp0 dsp). !!!!
-!!!!! !!!!
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-The configuration program asks one DMA channel and two interrupts. One IRQ
-and one DMA is used by the MSS codec. The second IRQ is required for the
-MPU401 mode (you have to use different IRQs for both purposes).
-There were earlier two DMA channels for SoundScape but the current driver
-version requires just one.
-
-The SoundScape card has a Motorola microcontroller which must initialized
-_after_ boot (the driver doesn't initialize it during boot).
-The initialization is done by running the 'ssinit' program which is
-distributed in the snd-util-3.0.tar.gz package. You have to edit two
-defines in the ssinit.c and then compile the program. You may run ssinit
-manually (after each boot) or add it to /etc/rc.d/rc.local.
-
-The ssinit program needs the microcode file that comes with the DOS/Windows
-driver of the card. You will need to use version 1.30.00 or later
-of the microcode file (sndscape.co0 or sndscape.co1 depending on
-your card model). THE OLD sndscape.cod WILL NOT WORK. IT WILL HANG YOUR
-MACHINE. The only way to get the new microcode file is to download
-and install the DOS/Windows driver from ftp://ftp.ensoniq.com/pub.
-
-Then you have to select the proper microcode file to use: soundscape.co0
-is the right one for most cards and sndscape.co1 is for few (older) cards
-made by Reveal and/or Spea. The driver has capability to detect the card
-version during boot. Look at the boot log messages in /var/adm/messages
-and locate the sound driver initialization message for the SoundScape
-card. If the driver displays string <Ensoniq Soundscape (old)>, you have
-an old card and you will need to use sndscape.co1. For other cards use
-soundscape.co0. New Soundscape revisions such as Elite and PnP use
-code files with higher numbers (.co2, .co3, etc.).
-
-NOTE! Ensoniq Soundscape VIVO is not compatible with other Soundscape cards.
- Currently it's possible to use it in Linux only with OSS/Linux
- drivers.
-
-Check /var/adm/messages after running ssinit. The driver prints
-the board version after downloading the microcode file. That version
-number must match the number in the name of the microcode file (extension).
-
-Running ssinit with a wrong version of the sndscape.co? file is not
-dangerous as long as you don't try to use a file called sndscape.cod.
-If you have initialized the card using a wrong microcode file (sounds
-are terrible), just modify ssinit.c to use another microcode file and try
-again. It's possible to use an earlier version of sndscape.co[01] but it
-may sound weird.
-
-MAD16 (Pro) and Mozart
-----------------------
-
-You need to enable just the MAD16 /Mozart support when configuring
-the driver. _Don't_ enable SB, MPU401 or MSS. However you will need the
-/dev/audio, /dev/sequencer and MIDI supports.
-
-Mozart and OPTi 82C928 (the original MAD16) chips don't support
-MPU401 mode so enter just 0 when the configuration program asks the
-MPU/MIDI I/O base. The MAD16 Pro (OPTi 82C929) and 82C930 chips have MPU401
-mode.
-
-TB Tropez is based on the 82C929 chip. It has two MIDI ports.
-The one connected to the MAD16 chip is the second one (there is a second
-MIDI connector/pins somewhere??). If you have not connected the second MIDI
-port, just disable the MIDI port of MAD16. The 'Maui' compatible synth of
-Tropez is jumper configurable and not connected to the MAD16 chip (the
-Maui driver can be used with it).
-
-Some MAD16 based cards may cause feedback, whistle or terrible noise if the
-line3 mixer channel is turned too high. This happens at least with Shuttle
-Sound System. Current driver versions set volume of line3 low enough so
-this should not be a problem.
-
-If you have a MAD16 card which have an OPL4 (FM + Wave table) synthesizer
-chip (_not_ an OPL3), you have to append a line containing #define MAD16_OPL4
-to the file linux/drivers/sound/local.h (after running make config).
-
-MAD16 cards having a CS4231 codec support full duplex mode. This mode
-can be enabled by configuring the card to use two DMA channels. Possible
-DMA channel pairs are: 0&1, 1&0 and 3&0.
-
-NOTE! Cards having an OPTi 82C924/82C925 chip work with OSS/Free only in
-non-PnP mode (usually jumper selectable). The PnP mode is supported only
-by OSS/Linux.
-
-MV Jazz (ProSonic)
-------------------
-
-The Jazz16 driver is just a hack made to the SB Pro driver. However it works
-fairly well. You have to enable SB, SB Pro (_not_ SB16) and MPU401 supports
-when configuring the driver. The configuration program asks later if you
-want support for MV Jazz16 based cards (after asking SB base address). Answer
-'y' here and the driver asks the second (16 bit) DMA channel.
-
-The Jazz16 driver uses the MPU401 driver in a way which will cause
-problems if you have another MPU401 compatible card. In this case you must
-give address of the Jazz16 based MPU401 interface when the config
-program prompts for the MPU401 information. Then look at the MPU401
-specific section for instructions about configuring more than one MPU401 cards.
-
-Logitech Soundman Wave
-----------------------
-
-Read the above MV Jazz specific instructions first.
-
-The Logitech SoundMan Wave (don't confuse this with the SM16 or SM Games) is
-a MV Jazz based card which has an additional OPL4 based wave table
-synthesizer. The OPL4 chip is handled by an on board microcontroller
-which must be initialized during boot. The config program asks if
-you have a SM Wave immediately after asking the second DMA channel of jazz16.
-If you answer 'y', the config program will ask name of the file containing
-code to be loaded to the microcontroller. The file is usually called
-MIDI0001.BIN and it's located in the DOS/Windows driver directory. The file
-may also be called as TSUNAMI.BIN or something else (older cards?).
-
-The OPL4 synth will be inaccessible without loading the microcontroller code.
-
-Also remember to enable SB MPU401 support if you want to use the OPL4 mode.
-(Don't enable the 'normal' MPU401 device as with some earlier driver
-versions (pre 3.5-alpha8)).
-
-NOTE! Don't answer 'y' when the driver asks about SM Games support
- (the next question after the MIDI0001.BIN name). However
- answering 'y' doesn't cause damage your computer so don't panic.
-
-Sound Galaxies
---------------
-
-There are many different Sound Galaxy cards made by Aztech. The 8 bit
-ones are fully SB or SB Pro compatible and there should be no problems
-with them.
-
-The older 16 bit cards (SG Pro16, SG NX Pro16, Nova and Lyra) have
-an EEPROM chip for storing the configuration data. There is a microcontroller
-which initializes the card to match the EEPROM settings when the machine
-is powered on. These cards actually behave just like they have jumpers
-for all of the settings. Configure driver for MSS, MPU, SB/SB Pro and OPL3
-supports with these cards.
-
-There are some new Sound Galaxies in the market. I have no experience with
-them so read the card's manual carefully.
-
-ESS ES1688 and ES688 'AudioDrive' based cards
----------------------------------------------
-
-Support for these two ESS chips is embedded in the SB driver.
-Configure these cards just like SB. Enable the 'SB MPU401 MIDI port'
-if you want to use MIDI features of ES1688. ES688 doesn't have MPU mode
-so you don't need to enable it (the driver uses normal SB MIDI automatically
-with ES688).
-
-NOTE! ESS cards are not compatible with MSS/WSS so don't worry if MSS support
-of OSS doesn't work with it.
-
-There are some ES1688/688 based sound cards and (particularily) motherboards
-which use software configurable I/O port relocation feature of the chip.
-This ESS proprietary feature is supported only by OSS/Linux.
-
-There are ES1688 based cards which use different interrupt pin assignment than
-recommended by ESS (5, 7, 9/2 and 10). In this case all IRQ's don't work.
-At least a card called (Pearl?) Hypersound 16 supports IRQ15 but it doesn't
-work.
-
-ES1868 is a PnP chip which is (supposed to be) compatible with ESS1688
-brobably works with OSS/Free after initialization using isapnptools.
-
-Reveal cards
-------------
-
-There are several different cards made/marketed by Reveal. Some of them
-are compatible with SoundScape and some use the MAD16 chip. You may have
-to look at the card and try to identify its origin.
-
-Diamond
--------
-
-The oldest (Sierra Aria based) sound cards made by Diamond are not supported
-(they may work if the card is initialized using DOS). The recent (LX?)
-models are based on the MAD16 chip which is supported by the driver.
-
-Audio Excel DSP16
------------------
-
-Support for this card is currently not functional. A new driver for it
-should be available later this year.
-
-PCMCIA cards
-------------
-
-Sorry, can't help. Some cards may work and some don't.
-
-TI TM4000M notebooks
---------------------
-
-These computers have a built in sound support based on the Jazz chipset.
-Look at the instructions for MV Jazz (above). It's also important to note
-that there is something wrong with the mouse port and sound at least on
-some TM models. Don't enable the "C&T 82C710 mouse port support" when
-configuring Linux. Having it enabled is likely to cause mysterious problems
-and kernel failures when sound is used.
-
-miroSOUND
----------
-
-The miroSOUND PCM12 has been used successfully. This card is based on
-the MAD16, OPL4, and CS4231A chips and everything said in the section
-about MAD16 cards applies here, too. The only major difference between
-the PCM12 and other MAD16 cards is that instead of the mixer in the
-CS4231 codec a separate mixer controlled by an on-board 80C32
-microcontroller is used. Control of the mixer takes place via the ACI
-(miro's audio control interface) protocol that is implemented in a
-separate lowlevel driver. Make sure you compile this ACI driver
-together with the normal MAD16 support when you use a miroSOUND PCM12
-card. The ACI mixer is controlled by /dev/mixer and the CS4231 mixer
-by /dev/mixer2. You usually don't want to change anything on the
-CS4231 mixer.
-
-The miroSOUND PCM12 is capable of full duplex operation (simultaneous
-PCM replay and recording), which allows you to implement nice
-real-time signal processing audio effect software and network
-telephones. The ACI mixer has to be configured into a special "solo"
-mode for duplex operation in order to avoid feedback caused by the
-mixer (input hears output signal). See lowlevel/aci.c for details on
-the ioctl() for activating the "solo" mode.
-
-The following configuration parameters have worked fine for the PCM12
-in Markus Kuhn's system, many other configurations might work, too:
-CONFIG_MAD16_BASE=0x530, CONFIG_MAD16_IRQ=11, CONFIG_MAD16_DMA=3,
-CONFIG_MAD16_DMA2=0, CONFIG_MAD16_MPU_BASE=0x330, CONFIG_MAD16_MPU_IRQ=10,
-DSP_BUFFSIZE=65536, SELECTED_SOUND_OPTIONS=0x00281000.
-
-The miroSOUND PCM1 pro and the PCM20 are very similar to the PCM12.
-Perhaps the same ACI driver also works for these cards, however this
-has never actually been tested. The PCM20 contains a radio tuner,
-which is also controlled by ACI. This radio tuner is currently not
-supported by the ACI driver, but documentation for it was provided by
-miro and ACI tuner support could easily be added if someone is really
-interested.
-
-Compaq Deskpro XL
------------------
-
-The builtin sound hardware of Compaq Deskpro XL is now supported.
-You need to configure the driver with MSS and OPL3 supports enabled.
-In addition you need to manually edit linux/drivers/sound/local.h and
-to add a line containing "#define DESKPROXL" if you used
-make menuconfig/xconfig.
-
-Others?
--------
-
-Since there are so many different sound cards, it's likely that I have
-forgotten to mention many of them. Please inform me if you know yet another
-card which works with Linux, please inform me (or is anybody else
-willing to maintain a database of supported cards (just like in XF86)?).
-
-Cards not supported yet
-=======================
-
-Please check the version of sound driver you are using before
-complaining that your card is not supported. It's possible you are
-using a driver version which was released months before your card was
-introduced. The driver's release date is listed after its version number in a
-"cat /dev/sndstat" printout and in the file linux/drivers/sound/soundvers.h.
-
-First of all, there is an easy way to make most sound cards work with Linux.
-Just use the DOS based driver to initialize the card to a known state, then use
-loadlin.exe to boot Linux. If Linux is configured to use the same I/O, IRQ and
-DMA numbers as DOS, the card could work.
-(ctrl-alt-del can be used in place of loadlin.exe but it doesn't work with
-new motherboards). This method works also with all/most PnP sound cards.
-
-Don't get fooled with SB compatibility. Most cards are compatible with
-SB but that may require a TSR which is not possible with Linux. If
-the card is compatible with MSS, it's a better choice. Some cards
-don't work in the SB and MSS modes at the same time.
-
-Then there are cards which are no longer manufactured and/or which
-are relatively rarely used (such as the 8 bit ProAudioSpectrum
-models). It's extremely unlikely that such cards ever get supported.
-Adding support for a new card requires much work and increases time
-required in maintaining the driver (some changes need to be done
-to all low level drivers and be tested too, maybe with multiple
-operating systems). For this reason I have made a decision to not support
-obsolete cards. It's possible that someone else makes a separately
-distributed driver (diffs) for the card.
-
-Writing a driver for a new card is not possible if there are no
-programming information available about the card. If you don't
-find your new card from this file, look from the home page
-(http://www.opensound.com/ossfree). Then please contact
-manufacturer of the card and ask if they have (or are willing to)
-released technical details of the card. Do this before contacting me. I
-can only answer 'no' if there are no programming information available.
-
-I have made decision to not accept code based on reverse engineering
-to the driver. There are three main reasons: First I don't want to break
-relationships to sound card manufacturers. The second reason is that
-maintaining and supporting a driver without any specs will be a pain.
-The third reason is that companies have freedom to refuse selling their
-products to other than Windows users.
-
-Some companies don't give low level technical information about their
-products to public or at least their require signing a NDA. It's not
-possible to implement a freeware driver for them. However it's possible
-that support for such cards become available in the commercial version
-of this driver (see http://www.4Front-tech.com/oss.html for more info).
-
-There are some common audio chipsets that are not supported yet. For example
-Sierra Aria and IBM Mwave. It's possible that these architectures
-get some support in future but I can't make any promises. Just look
-at the home page (http://www.opensound.com/ossfree/new_cards.html)
-for latest info.
-
-Information about unsupported sound cards and chipsets is welcome as well
-as free copies of sound cards, SDKs and operating systems.
-
-If you have any corrections and/or comments, please contact me.
-
-Hannu Savolainen
-hannu@opensound.com
-
-Personal home page: http://www.compusonic.fi/~hannu
-home page of OSS/Free: http://www.opensound.com/ossfree
-
-home page of commercial OSS
-(Open Sound System) drivers: http://www.opensound.com/oss.html
diff --git a/drivers/sound/Readme.linux b/drivers/sound/Readme.linux
deleted file mode 100644
index 97fe386b3..000000000
--- a/drivers/sound/Readme.linux
+++ /dev/null
@@ -1,85 +0,0 @@
-Installation
-------------
-
-IMPORTANT! Read this if you are installing a separately
- distributed version of this driver.
-
- Check that your kernel version works with this
- release of the driver (see Readme). Also verify
- that your current kernel version doesn't have more
- recent sound driver version than this one. IT'S HIGHLY
- RECOMMENDED THAT YOU USE THE SOUND DRIVER VERSION THAT
- IS DISTRIBUTED WITH KERNEL SOURCES.
-
-- When installing separately distributed sound driver you should first
- read the above notice. Then try to find proper directory where and how
- to install the driver sources. You should not try to install a separately
- distributed driver version if you are not able to find the proper way
- yourself (in this case use the version that is distributed with kernel
- sources). Remove old version of linux/drivers/sound directory before
- installing new files.
-
-- To build the device files you need to run the enclosed shell script
- (see below). You need to do this only when installing sound driver
- first time or when upgrading to much recent version than the earlier
- one.
-
-- Configure and compile Linux as normally (remember to include the
- sound support during "make config"). Please refer to kernel documentation
- for instructions about configuring and compiling kernel. File Readme.cards
- contains card specific instructions for configuring this driver for
- use with various sound cards.
-
-Boot time configuration (using lilo and insmod)
------------------------------------------------
-
-This information has been removed. Too many users didn't believe
-that it's really not necessary to use this method. Please look at
-Readme of sound driver version 3.0.1 if you still want to use this method.
-
-Problems
---------
-
-If you have any kind of problems, there is a debugging feature which
-could help you to solve the problem. To use it, just execute the
-command:
-
- cat /dev/sndstat
-
-and look at the output. It should display some useful info about the
-driver configuration. If there is no /dev/sndstat
-(/dev/sndstat: No such file or directory), ensure that you have executed the
-soundinstall script (at the end of this file).
-
-Common error messages:
-
-- /dev/???????: No such file or directory.
-Run the script at the end of this file.
-
-- /dev/???????: No such device.
-You are not running kernel which contains the sound driver. When using
-modularized sound driver this error means that the sound driver is not
-loaded.
-
-- /dev/????: No such device or address.
-Sound driver didn't detect suitable card when initializing. Please look at
-Readme.cards for info about configuring the driver with your card. Also
-check for possible boot (insmod) time error messages in /var/adm/messages.
-
-- Other messages or problems
-Please check http://www.opensound.com/ossfree for more info.
-
-Hannu Savolainen
-hannu@opensound.com
-
------------------ cut here ------------------------------
-SURPRISE SURPRISE!!!
-
-The device file creation script that used to be here earlier is
-obviously not here any more.
-
-Why?
-
-Because you do not need it. All Linux distributions have the
-device files properly created (yes they are) so you should not
-try to run any scripts which create them.
diff --git a/drivers/sound/Readme.modules b/drivers/sound/Readme.modules
deleted file mode 100644
index 670fbe87b..000000000
--- a/drivers/sound/Readme.modules
+++ /dev/null
@@ -1,99 +0,0 @@
-Building a modular sound driver
-================================
-
- The following information is current as of linux-2.1.85. Check the other
-readme files, especially Readme.cards, for information not specific to
-making sound modular.
-
- First, configure your kernel. This is an idea of what you should be
-setting in the sound section:
-
-<M> Sound card support
-
-<M> 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
-
- I have SoundBlaster. Select your card from the list.
-
-<M> Generic OPL2/OPL3 FM synthesizer support
-<M> FM synthesizer (YM3812/OPL-3) support
-
- If you don't set these, you will probably find you can play .wav files
-but not .midi. As the help for them says, set them unless you know your
-card does not use one of these chips for FM support.
-
- Once you are configured, make zlilo, modules, modules_install; reboot.
-Note that it is no longer necessary or possible to configure sound in the
-drivers/sound dir. Now one simply configures and makes one's kernel and
-modules in the usual way.
-
- Then, add to your /etc/modules.conf or /etc/conf.modules something like:
-
-alias char-major-14 sb
-post-install sb /sbin/modprobe "-k" "adlib_card"
-options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
-options adlib_card io=0x388 # FM synthesizer
-
- The effect of this is that the sound driver and all necessary bits and
-pieces autoload on demand, assuming you use kerneld (a sound choice) and
-autoclean when not in use. Also, options for the device drivers are
-set. They will not work without them. Change as appropriate for your card.
-If you are not yet using the very cool kerneld, you will have to "modprobe
--k sb" yourself to get things going. Eventually things may be fixed so
-that this kludgery is not necessary; for the time being, it seems to work
-well.
-
- Replace 'sb' with the driver for your card, and give it the right
-options. To find the filename of the driver, look in
-/lib/modules/<kernel-version>/misc. Mine looks like:
-
-adlib_card.o # This is the generic OPLx driver
-opl3.o # The OPL3 driver
-sb.o # <<The SoundBlaster driver. Yours may differ.>>
-sound.o # The sound driver
-uart401.o # Used by sb, maybe other cards
-
- Whichever card you have, try feeding it the options that would be the
-default if you were making the driver wired, not as modules. You can look
-at the init_module() code for the card to see what args are expected.
-
- Note that at present there is no way to configure the io, irq and other
-parameters for the modular drivers as one does for the wired drivers.. One
-needs to pass the modules the necessary parameters as arguments, either
-with /etc/modules.conf or with command-line args to modprobe, e.g.
-
-modprobe -k sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330
-modprobe -k adlib_card io=0x388
-
- recommend using /etc/modules.conf.
-
-Persistent DMA Buffers:
-
-The sound modules normally allocate DMA buffers during open() and
-deallocate them during close(). Linux can often have problems allocating
-DMA buffers for ISA cards on machines with more than 16MB RAM. This is
-because ISA DMA buffers must exist below the 16MB boundry and it is quite
-possible that we can't find a large enough free block in this region after
-the machine has been running for any amount of time. The way to avoid this
-problem is to allocate the DMA buffers during module load and deallocate
-them when the module is unloaded. For this to be effective we need to load
-the sound modules right after the kernel boots, either manually or by an
-init script, and keep them around until we shut down. This is a little
-wasteful of RAM, but it guarantees that sound always works.
-
-To make the sound driver use persistent DMA buffers we need to pass the
-sound.o module a "dmabuf=1" command-line argument. This is normally done
-in /etc/conf.modules (or the more proper /etc/modules.conf) like so:
-
-options sound dmabuf=1
-
-If you have 16MB or less RAM or a PCI sound card, this is wasteful and
-unnecessary. It is possible that machine with 16MB or less RAM will find
-this option useful, but if your machine is so memory-starved that it
-cannot find a 64K block free, you will be wasting even more RAM by keeping
-the sound modules loaded and the DMA buffers allocated when they are not
-needed. The proper solution is to upgrade your RAM. But you do also have
-this improper solution as well. Use it wisely.
-
- I'm afraid I know nothing about anything but my setup, being more of a
-text-mode guy anyway. If you have options for other cards or other helpful
-hints, send them to me, Jim Bray, jb@as220.org, http://as220.org/jb.
diff --git a/drivers/sound/ad1816.c b/drivers/sound/ad1816.c
new file mode 100644
index 000000000..6d7c2e13e
--- /dev/null
+++ b/drivers/sound/ad1816.c
@@ -0,0 +1,1417 @@
+/*
+
+AD1816 lowlevel sound driver for Linux 2.2.0 and above
+
+Copyright (C) 1998 by Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
+Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the 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
+
+-------------------------------------------------------------------------------
+NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE! NOTE!
+
+This software is still under development. New versions of the driver
+are available from:
+ http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
+or
+ http://www.tu-darmstadt.de/~tek01/projects/linux.html
+
+Please report any bugs to: tek@rbg.informatik.tu-darmstadt.de
+
+-------------------------------------------------------------------------------
+
+version: 1.2
+cvs: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $
+status: experimental
+date: 1999/01/16
+
+Changes:
+ Oleg Drokin: Some cleanup of load/unload functions. 1998/11/24
+
+ Thorsten Knabe: attach and unload rewritten,
+ some argument checks added 1998/11/30
+
+ Thorsten Knabe: Buggy isa bridge workaround added 1999/01/16
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include "soundmodule.h"
+#include "sound_config.h"
+
+#ifdef CONFIG_AD1816
+
+#define DEBUGNOISE(x)
+#define DEBUGINFO(x)
+#define DEBUGLOG(x) x
+#define DEBUGWARN(x) x
+
+#define CHECK_FOR_POWER { int timeout=100; \
+ while (timeout > 0 && (inb(devc->base)&0x80)!= 0x80) {\
+ timeout--; \
+ } \
+ if (timeout==0) {\
+ printk("ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
+ } \
+}
+
+/* structure to hold device specific information */
+typedef struct
+{
+ int base; /* set in attach */
+ int irq;
+ int dma_playback;
+ int dma_capture;
+
+ int speed; /* open */
+ int channels;
+ int audio_format;
+ unsigned char format_bits;
+ int audio_mode;
+ int opened;
+
+ int recmask; /* setup */
+ int supported_devices;
+ int supported_rec_devices;
+ unsigned short levels[SOUND_MIXER_NRDEVICES];
+ int dev_no; /* this is the # in audio_devs and NOT
+ in ad1816_info */
+ int irq_ok;
+ int *osp;
+
+}
+
+ad1816_info;
+
+static int nr_ad1816_devs = 0;
+
+static int ad1816_clockfreq=33000;
+
+/* for backward mapping of irq to sound device */
+
+static volatile char irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+
+/* supported audio formats */
+static int ad_format_mask =
+AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW;
+
+/* array of device info structures */
+static ad1816_info dev_info[MAX_AUDIO_DEV];
+
+
+/* ------------------------------------------------------------------- */
+
+/* functions for easier access to inderect registers */
+
+static int ad_read (ad1816_info * devc, int reg)
+{
+ unsigned long flags;
+ int result;
+
+ CHECK_FOR_POWER;
+
+ save_flags (flags); /* make register access atomic */
+ cli ();
+ outb ((unsigned char) (reg & 0x3f), devc->base+0);
+ result = inb(devc->base+2);
+ result+= inb(devc->base+3)<<8;
+ restore_flags (flags);
+
+ return (result);
+}
+
+
+static void ad_write (ad1816_info * devc, int reg, int data)
+{
+ unsigned long flags;
+
+ CHECK_FOR_POWER;
+
+ save_flags (flags); /* make register access atomic */
+ cli ();
+ outb ((unsigned char) (reg & 0xff), devc->base+0);
+ outb ((unsigned char) (data & 0xff),devc->base+2);
+ outb ((unsigned char) ((data>>8)&0xff),devc->base+3);
+ restore_flags (flags);
+
+}
+
+/* ------------------------------------------------------------------- */
+
+/* function interface required by struct audio_driver */
+
+static void ad1816_halt_input (int dev)
+{
+ unsigned long flags;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+ unsigned char buffer;
+
+ DEBUGINFO (printk("ad1816: halt_input called\n"));
+
+ save_flags (flags);
+ cli ();
+
+ if(!isa_dma_bridge_buggy) {
+ disable_dma(audio_devs[dev]->dmap_in->dma);
+ }
+
+ buffer=inb(devc->base+9);
+ if (buffer & 0x01) {
+ /* disable capture */
+ outb(buffer & ~0x01,devc->base+9);
+ }
+
+ if(!isa_dma_bridge_buggy) {
+ enable_dma(audio_devs[dev]->dmap_in->dma);
+ }
+
+ /* Clear interrupt status */
+ outb (~0x40, devc->base+1);
+
+ devc->audio_mode &= ~PCM_ENABLE_INPUT;
+ restore_flags (flags);
+}
+
+static void ad1816_halt_output (int dev)
+{
+ unsigned long flags;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ unsigned char buffer;
+
+ DEBUGINFO (printk("ad1816: halt_output called!\n"));
+
+ save_flags (flags);
+ cli ();
+ /* Mute pcm output */
+ ad_write(devc, 4, ad_read(devc,4)|0x8080);
+
+ if(!isa_dma_bridge_buggy) {
+ disable_dma(audio_devs[dev]->dmap_out->dma);
+ }
+
+ buffer=inb(devc->base+8);
+ if (buffer & 0x01) {
+ /* disable capture */
+ outb(buffer & ~0x01,devc->base+8);
+ }
+
+ if(!isa_dma_bridge_buggy) {
+ enable_dma(audio_devs[dev]->dmap_out->dma);
+ }
+
+ /* Clear interrupt status */
+ outb ((unsigned char)~0x80, devc->base+1);
+
+ devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+ restore_flags (flags);
+}
+
+static void ad1816_output_block (int dev, unsigned long buf,
+ int count, int intrflag)
+{
+ unsigned long flags;
+ unsigned long cnt;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ DEBUGINFO(printk("ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
+
+ cnt = count/4 - 1;
+
+ save_flags (flags);
+ cli ();
+
+ /* set transfer count */
+ ad_write (devc, 8, cnt & 0xffff);
+
+ devc->audio_mode |= PCM_ENABLE_OUTPUT;
+ restore_flags (flags);
+}
+
+
+static void ad1816_start_input (int dev, unsigned long buf, int count,
+ int intrflag)
+{
+ unsigned long flags;
+ unsigned long cnt;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ DEBUGINFO(printk("ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
+
+ cnt = count/4 - 1;
+
+ save_flags (flags); /* make register access atomic */
+ cli ();
+
+ /* set transfer count */
+ ad_write (devc, 10, cnt & 0xffff);
+
+ devc->audio_mode |= PCM_ENABLE_INPUT;
+ restore_flags (flags);
+}
+
+
+static int ad1816_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+ return -(EINVAL);
+}
+
+
+static int ad1816_prepare_for_input (int dev, int bsize, int bcount)
+{
+ unsigned long flags;
+ unsigned int freq;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+ unsigned char fmt_bits;
+
+ DEBUGINFO (printk ("ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
+
+ save_flags (flags);
+ cli ();
+
+ fmt_bits= (devc->format_bits&0x7)<<3;
+
+ /* set mono/stereo mode */
+ if (devc->channels > 1) {
+ fmt_bits |=0x4;
+ }
+
+ /* set Mono/Stereo in playback/capture register */
+ outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8);
+ outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
+
+ /* If compiled into kernel, AD1816_CLOCK is defined, so use it */
+#ifdef AD1816_CLOCK
+ ad1816_clockfreq=AD1816_CLOCK;
+#endif
+
+ /* capture/playback frequency correction for soundcards
+ with clock chips != 33MHz (allowed range 5 - 100 kHz) */
+
+ if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
+ ad1816_clockfreq=33000;
+ }
+
+ freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq;
+
+ /* write playback/capture speeds */
+ ad_write (devc, 2, freq & 0xffff);
+ ad_write (devc, 3, freq & 0xffff);
+
+ restore_flags (flags);
+
+ ad1816_halt_input(dev);
+ return 0;
+}
+
+static int ad1816_prepare_for_output (int dev, int bsize, int bcount)
+{
+ unsigned long flags;
+ unsigned int freq;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+ unsigned char fmt_bits;
+
+ DEBUGINFO (printk ("ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
+
+ save_flags (flags); /* make register access atomic */
+ cli ();
+
+ fmt_bits= (devc->format_bits&0x7)<<3;
+ /* set mono/stereo mode */
+ if (devc->channels > 1) {
+ fmt_bits |=0x4;
+ }
+
+ /* write format bits to playback/capture registers */
+ outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8);
+ outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
+
+#ifdef AD1816_CLOCK
+ ad1816_clockfreq=AD1816_CLOCK;
+#endif
+
+ /* capture/playback frequency correction for soundcards
+ with clock chips != 33MHz (allowed range 5 - 100 kHz)*/
+
+ if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
+ ad1816_clockfreq=33000;
+ }
+
+ freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq;
+
+ /* write playback/capture speeds */
+ ad_write (devc, 2, freq & 0xffff);
+ ad_write (devc, 3, freq & 0xffff);
+
+ restore_flags (flags);
+
+ ad1816_halt_output(dev);
+ return 0;
+
+}
+
+static void ad1816_trigger (int dev, int state)
+{
+ unsigned long flags;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ DEBUGINFO (printk("ad1816: trigger called! (devc=%d,devc->base=%d\n",devc,devc->base));
+
+ /* mode may have changed */
+
+ save_flags (flags); /* make register access atomic */
+ cli ();
+
+ /* mask out modes not specified on open call */
+ state &= devc->audio_mode;
+
+ /* setup soundchip to new io-mode */
+ if (state & PCM_ENABLE_INPUT) {
+ /* enable capture */
+ outb(inb(devc->base+9)|0x01, devc->base+9);
+ } else {
+ /* disable capture */
+ outb(inb(devc->base+9)&~0x01, devc->base+9);
+ }
+
+ if (state & PCM_ENABLE_OUTPUT) {
+ /* enable playback */
+ outb(inb(devc->base+8)|0x01, devc->base+8);
+ /* unmute pcm output */
+ ad_write(devc, 4, ad_read(devc,4)&~0x8080);
+ } else {
+ /* mute pcm output */
+ ad_write(devc, 4, ad_read(devc,4)|0x8080);
+ /* disable capture */
+ outb(inb(devc->base+8)&~0x01, devc->base+8);
+ }
+ restore_flags (flags);
+}
+
+
+/* halt input & output */
+static void ad1816_halt (int dev)
+{
+ ad1816_halt_input(dev);
+ ad1816_halt_output(dev);
+}
+
+static void ad1816_reset (int dev)
+{
+ ad1816_halt (dev);
+}
+
+/* set playback speed */
+static int ad1816_set_speed (int dev, int arg)
+{
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ if (arg == 0) {
+ return devc->speed;
+ }
+ /* range checking */
+ if (arg < 4000) {
+ arg = 4000;
+ }
+ if (arg > 55000) {
+ arg = 55000;
+ }
+
+ devc->speed = arg;
+ return devc->speed;
+
+}
+
+static unsigned int ad1816_set_bits (int dev, unsigned int arg)
+{
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ static struct format_tbl
+ {
+ int format;
+ unsigned char bits;
+ }
+ format2bits[] =
+ {
+ {
+ 0, 0
+ }
+ ,
+ {
+ AFMT_MU_LAW, 1
+ }
+ ,
+ {
+ AFMT_A_LAW, 3
+ }
+ ,
+ {
+ AFMT_IMA_ADPCM, 0
+ }
+ ,
+ {
+ AFMT_U8, 0
+ }
+ ,
+ {
+ AFMT_S16_LE, 2
+ }
+ ,
+ {
+ AFMT_S16_BE, 6
+ }
+ ,
+ {
+ AFMT_S8, 0
+ }
+ ,
+ {
+ AFMT_U16_LE, 0
+ }
+ ,
+ {
+ AFMT_U16_BE, 0
+ }
+ };
+ int i, n = sizeof (format2bits) / sizeof (struct format_tbl);
+
+ /* return current format */
+ if (arg == 0) {
+ return devc->audio_format;
+ }
+
+ devc->audio_format = arg;
+
+ /* search matching format bits */
+ for (i = 0; i < n; i++) {
+ if (format2bits[i].format == arg) {
+ devc->format_bits = format2bits[i].bits;
+ devc->audio_format = arg;
+ return arg;
+ }
+ }
+ /* Still hanging here. Something must be terribly wrong */
+ devc->format_bits = 0;
+ return devc->audio_format = AFMT_U8;
+}
+
+static short ad1816_set_channels (int dev, short arg)
+{
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ if (arg != 1 && arg != 2) {
+ return devc->channels;
+ }
+
+ devc->channels = arg;
+ return arg;
+}
+
+/* open device */
+static int ad1816_open (int dev, int mode)
+{
+ ad1816_info *devc = NULL;
+ unsigned long flags;
+
+ /* is device number valid ? */
+ if (dev < 0 || dev >= num_audiodevs) {
+ return -(ENXIO);
+ }
+
+ /* get device info of this dev */
+ devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ /* make check if device already open atomic */
+ save_flags (flags);
+ cli ();
+
+ if (devc->opened) {
+ restore_flags (flags);
+ return -(EBUSY);
+ }
+
+ /* mark device as open */
+ devc->opened = 1;
+
+ devc->audio_mode = 0;
+ devc->speed = 8000;
+ devc->audio_format=AFMT_U8;
+ devc->channels=1;
+
+ ad1816_reset(devc->dev_no); /* halt all pending output */
+ restore_flags (flags);
+ return 0;
+}
+
+static void ad1816_close (int dev) /* close device */
+{
+ unsigned long flags;
+ ad1816_info *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ save_flags (flags);
+ cli ();
+
+ /* halt all pending output */
+ ad1816_reset(devc->dev_no);
+
+ devc->opened = 0;
+ devc->audio_mode = 0;
+ devc->speed = 8000;
+ devc->audio_format=AFMT_U8;
+ devc->format_bits = 0;
+
+
+ restore_flags (flags);
+}
+
+
+/* ------------------------------------------------------------------- */
+
+/* Audio driver structure */
+
+static struct audio_driver ad1816_audio_driver =
+{
+ ad1816_open,
+ ad1816_close,
+ ad1816_output_block,
+ ad1816_start_input,
+ ad1816_ioctl,
+ ad1816_prepare_for_input,
+ ad1816_prepare_for_output,
+ ad1816_halt,
+ NULL,
+ NULL,
+ ad1816_halt_input,
+ ad1816_halt_output,
+ ad1816_trigger,
+ ad1816_set_speed,
+ ad1816_set_bits,
+ ad1816_set_channels,
+ NULL,
+ NULL
+};
+
+
+/* ------------------------------------------------------------------- */
+
+/* Interrupt handler */
+
+void ad1816_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
+{
+ unsigned char status;
+ ad1816_info *devc;
+ int dev;
+ unsigned long flags;
+
+
+ if (irq < 0 || irq > 15) {
+ printk ("ad1816: Got bogus interrupt %d\n", irq);
+ return;
+ }
+
+ dev = irq2dev[irq];
+
+ if (dev < 0 || dev >= num_audiodevs) {
+ printk ("ad1816: IRQ2AD1816-mapping failed for irq %d device %d\n", irq,dev);
+ return;
+ }
+
+ devc = (ad1816_info *) audio_devs[dev]->devc;
+
+ save_flags(flags);
+ cli();
+
+ /* read interrupt register */
+ status = inb (devc->base+1);
+ /* Clear all interrupt */
+ outb (~status, devc->base+1);
+
+ DEBUGNOISE (printk("ad1816: Got interrupt subclass %d\n",status));
+
+ devc->irq_ok=1;
+
+ if (status == 0) {
+ DEBUGWARN(printk ("ad1816: interrupt: Got interrupt, but no reason?\n"));
+ }
+ if (devc->opened && (devc->audio_mode & PCM_ENABLE_INPUT)
+ && (status&64)){
+ DMAbuf_inputintr (dev);
+ }
+
+ if (devc->opened && (devc->audio_mode & PCM_ENABLE_OUTPUT) &&
+ (status & 128)) {
+ DMAbuf_outputintr (dev, 1);
+ }
+ restore_flags(flags);
+}
+
+/* ------------------------------------------------------------------- */
+
+/* Mixer stuff */
+
+struct mixer_def {
+ unsigned int regno: 7;
+ unsigned int polarity:1; /* 0=normal, 1=reversed */
+ unsigned int bitpos:4;
+ unsigned int nbits:4;
+};
+
+static char mix_cvt[101] = {
+ 0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+ 43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
+ 65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
+ 80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
+ 91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
+ 100
+};
+
+typedef struct mixer_def mixer_ent;
+
+/*
+ * Most of the mixer entries work in backwards. Setting the polarity field
+ * makes them to work correctly.
+ *
+ * The channel numbering used by individual soundcards is not fixed. Some
+ * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
+ * The current version doesn't try to compensate this.
+ */
+
+#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r) \
+ {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
+
+
+mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
+MIX_ENT(SOUND_MIXER_VOLUME, 14, 1, 8, 5, 14, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 5, 1, 8, 6, 5, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_PCM, 4, 1, 8, 6, 4, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 18, 1, 8, 5, 18, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_MIC, 19, 1, 8, 5, 19, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_CD, 15, 1, 8, 5, 15, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 20, 0, 8, 4, 20, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 17, 1, 8, 5, 17, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE2, 16, 1, 8, 5, 16, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE3, 39, 0, 9, 4, 39, 1, 0, 5)
+};
+
+
+static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
+{
+ 0x4343, /* Master Volume */
+ 0x3232, /* Bass */
+ 0x3232, /* Treble */
+ 0x0000, /* FM */
+ 0x4343, /* PCM */
+ 0x0000, /* PC Speaker */
+ 0x0000, /* Ext Line */
+ 0x0000, /* Mic */
+ 0x0000, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x0000, /* SB PCM */
+ 0x0000, /* Recording level */
+ 0x0000, /* Input gain */
+ 0x0000, /* Output gain */
+ 0x0000, /* Line1 */
+ 0x0000, /* Line2 */
+ 0x0000 /* Line3 (usually line in)*/
+};
+
+#define LEFT_CHN 0
+#define RIGHT_CHN 1
+
+
+
+static int
+ad1816_set_recmask (ad1816_info * devc, int mask)
+{
+ unsigned char recdev;
+ int i, n;
+
+ mask &= devc->supported_rec_devices;
+
+ n = 0;
+ /* Count selected device bits */
+ for (i = 0; i < 32; i++) {
+ if (mask & (1 << i)) {
+ n++;
+ }
+ }
+
+ if (n == 0) {
+ mask = SOUND_MASK_MIC;
+ } else if (n != 1) { /* Too many devices selected */
+ /* Filter out active settings */
+ mask &= ~devc->recmask;
+
+ n = 0;
+ /* Count selected device bits */
+ for (i = 0; i < 32; i++) {
+ if (mask & (1 << i)) {
+ n++;
+ }
+ }
+
+ if (n != 1) {
+ mask = SOUND_MASK_MIC;
+ }
+ }
+
+ switch (mask) {
+ case SOUND_MASK_MIC:
+ recdev = 5;
+ break;
+
+ case SOUND_MASK_LINE:
+ recdev = 0;
+ break;
+
+ case SOUND_MASK_CD:
+ recdev = 2;
+ break;
+
+ case SOUND_MASK_LINE1:
+ recdev = 4;
+ break;
+
+ case SOUND_MASK_LINE2:
+ recdev = 3;
+ break;
+
+ case SOUND_MASK_VOLUME:
+ recdev = 1;
+ break;
+
+ default:
+ mask = SOUND_MASK_MIC;
+ recdev = 5;
+ }
+
+ recdev <<= 4;
+ ad_write (devc, 20,
+ (ad_read (devc, 20) & 0x8f8f) | recdev | (recdev<<8));
+
+ devc->recmask = mask;
+ return mask;
+}
+
+static void
+change_bits (int *regval, int dev, int chn, int newval)
+{
+ unsigned char mask;
+ int shift;
+
+ /* Reverse polarity*/
+
+ if (mix_devices[dev][chn].polarity == 1) {
+ newval = 100 - newval;
+ }
+
+ mask = (1 << mix_devices[dev][chn].nbits) - 1;
+ shift = mix_devices[dev][chn].bitpos;
+ /* Scale it */
+ newval = (int) ((newval * mask) + 50) / 100;
+ /* Clear bits */
+ *regval &= ~(mask << shift);
+ /* Set new value */
+ *regval |= (newval & mask) << shift;
+}
+
+static int
+ad1816_mixer_get (ad1816_info * devc, int dev)
+{
+ DEBUGINFO(printk("ad1816: mixer_get called!\n"));
+
+ /* range check + supported mixer check */
+ if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES ) {
+ return (-(EINVAL));
+ }
+ if (!((1 << dev) & devc->supported_devices)) {
+ return -(EINVAL);
+ }
+
+ return devc->levels[dev];
+}
+
+static int
+ad1816_mixer_set (ad1816_info * devc, int dev, int value)
+{
+ int left = value & 0x000000ff;
+ int right = (value & 0x0000ff00) >> 8;
+ int retvol;
+
+ int regoffs;
+ int val;
+ int valmute;
+
+ DEBUGINFO(printk("ad1816: mixer_set called!\n"));
+
+ if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES ) {
+ return -(EINVAL);
+ }
+
+ if (left > 100) {
+ left = 100;
+ }
+ if (left < 0) {
+ left = 0;
+ }
+ if (right > 100) {
+ right = 100;
+ }
+ if (right < 0) {
+ right = 0;
+ }
+
+ /* Mono control */
+ if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
+ right = left;
+ }
+ retvol = left | (right << 8);
+
+ /* Scale it */
+
+ left = mix_cvt[left];
+ right = mix_cvt[right];
+
+ /* reject all mixers that are not supported */
+ if (!(devc->supported_devices & (1 << dev))) {
+ return -(EINVAL);
+ }
+
+ /* sanity check */
+ if (mix_devices[dev][LEFT_CHN].nbits == 0) {
+ return -(EINVAL);
+ }
+
+ /* keep precise volume internal */
+ devc->levels[dev] = retvol;
+
+ /* Set the left channel */
+ regoffs = mix_devices[dev][LEFT_CHN].regno;
+ val = ad_read (devc, regoffs);
+ change_bits (&val, dev, LEFT_CHN, left);
+
+ valmute=val;
+
+ /* Mute bit masking on some registers */
+ if ( regoffs==5 || regoffs==14 || regoffs==15 ||
+ regoffs==16 || regoffs==17 || regoffs==18 ||
+ regoffs==19 || regoffs==39) {
+ if (left==0) {
+ valmute |= 0x8000;
+ } else {
+ valmute &= ~0x8000;
+ }
+ }
+ ad_write (devc, regoffs, valmute); /* mute */
+
+ /*
+ * Set the right channel
+ */
+
+ /* Was just a mono channel */
+ if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
+ return retvol;
+ }
+ regoffs = mix_devices[dev][RIGHT_CHN].regno;
+ val = ad_read (devc, regoffs);
+ change_bits (&val, dev, RIGHT_CHN, right);
+
+ valmute=val;
+ if ( regoffs==5 || regoffs==14 || regoffs==15 ||
+ regoffs==16 || regoffs==17 || regoffs==18 ||
+ regoffs==19 || regoffs==39) {
+ if (right==0) {
+ valmute |= 0x80;
+ } else {
+ valmute &= ~0x80;
+ }
+ }
+ ad_write (devc, regoffs, valmute); /* mute */
+
+ return retvol;
+}
+
+#define MIXER_DEVICES ( SOUND_MASK_VOLUME | \
+ SOUND_MASK_SYNTH | \
+ SOUND_MASK_PCM | \
+ SOUND_MASK_LINE | \
+ SOUND_MASK_LINE1 | \
+ SOUND_MASK_LINE2 | \
+ SOUND_MASK_LINE3 | \
+ SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_RECLEV \
+ )
+#define REC_DEVICES ( SOUND_MASK_LINE2 |\
+ SOUND_MASK_LINE |\
+ SOUND_MASK_LINE1 |\
+ SOUND_MASK_MIC |\
+ SOUND_MASK_CD |\
+ SOUND_MASK_VOLUME \
+ )
+
+static void
+ad1816_mixer_reset (ad1816_info * devc)
+{
+ int i;
+
+ devc->supported_devices = MIXER_DEVICES;
+
+ devc->supported_rec_devices = REC_DEVICES;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ if (devc->supported_devices & (1 << i)) {
+ ad1816_mixer_set (devc, i, default_mixer_levels[i]);
+ }
+ }
+ ad1816_set_recmask (devc, SOUND_MASK_MIC);
+}
+
+static int
+ad1816_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+ ad1816_info *devc = mixer_devs[dev]->devc;
+ int val;
+
+ DEBUGINFO(printk("ad1816: mixer_ioctl called!\n"));
+
+ /* Mixer ioctl */
+ if (((cmd >> 8) & 0xff) == 'M') {
+
+ /* set ioctl */
+ if (_IOC_DIR (cmd) & _IOC_WRITE) {
+ switch (cmd & 0xff){
+ case SOUND_MIXER_RECSRC:
+
+ if (get_user(val, (int *)arg)) {
+ return -EFAULT;
+ }
+ val=ad1816_set_recmask (devc, val);
+ return put_user(val, (int *)arg);
+ break;
+
+ default:
+ if (get_user(val, (int *)arg)){
+ return -EFAULT;
+ }
+ if ((val=ad1816_mixer_set (devc, cmd & 0xff, val))<0) {
+ return val;
+ } else {
+ return put_user(val, (int *)arg);
+ }
+ }
+ } else {
+ /* read ioctl */
+ switch (cmd & 0xff) {
+
+ case SOUND_MIXER_RECSRC:
+ val=devc->recmask;
+ return put_user(val, (int *)arg);
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ val=devc->supported_devices;
+ return put_user(val, (int *)arg);
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ val=devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
+ return put_user(val, (int *)arg);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ val=devc->supported_rec_devices;
+ return put_user(val, (int *)arg);
+ break;
+
+ case SOUND_MIXER_CAPS:
+ val=SOUND_CAP_EXCL_INPUT;
+ return put_user(val, (int *)arg);
+ break;
+
+ default:
+ if ((val=ad1816_mixer_get (devc, cmd & 0xff))<0) {
+ return val;
+ } else {
+ return put_user(val, (int *)arg);
+ }
+ }
+ }
+ } else {
+ /* not for mixer */
+ return -(EINVAL);
+ }
+}
+
+/* ------------------------------------------------------------------- */
+
+/* Mixer structure */
+
+static struct mixer_operations ad1816_mixer_operations =
+{
+ "AD1816",
+ "AD1816 Mixer",
+ ad1816_mixer_ioctl
+};
+
+
+/* ------------------------------------------------------------------- */
+
+/* stuff for card recognition, init and unloading */
+
+
+/* replace with probe routine */
+int probe_ad1816 ( struct address_info *hw_config )
+{
+ ad1816_info *devc = &dev_info[nr_ad1816_devs];
+ int io_base=hw_config->io_base;
+ int *osp=hw_config->osp;
+ int tmp;
+
+ printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
+ printk("ad1816: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $\n");
+ printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, isadmabug=%d\n",
+ hw_config->io_base,
+ hw_config->irq,
+ hw_config->dma,
+ hw_config->dma2,
+ isa_dma_bridge_buggy);
+
+ if (check_region (io_base, 16)) {
+ printk ("ad1816: I/O port 0x%03x not free\n", io_base);
+ return 0;
+ }
+
+ DEBUGLOG(printk ("ad1816: detect(%x)\n", io_base));
+
+ if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
+ printk ("ad1816: detect error - step 0\n");
+ return 0;
+ }
+
+ devc->base = io_base;
+ devc->irq_ok = 0;
+ devc->irq = 0;
+ devc->opened = 0;
+ devc->osp = osp;
+
+ /* base+0: bit 1 must be set but not 255 */
+ tmp=inb(devc->base);
+ if ( (tmp&0x80)==0 || tmp==255 ) {
+ DEBUGLOG (printk ("ad1816: Chip is not an AD1816 or chip is not active (Test 0)\n"));
+ return(0);
+ }
+
+
+ /* writes to ireg 8 are copied to ireg 9 */
+ ad_write(devc,8,12345);
+ if (ad_read(devc,9)!=12345) {
+ DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 1)\n"));
+ return(0);
+ }
+
+ /* writes to ireg 8 are copied to ireg 9 */
+ ad_write(devc,8,54321);
+ if (ad_read(devc,9)!=54321) {
+ DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 2)\n"));
+ return(0);
+ }
+
+ /* writes to ireg 10 are copied to ireg 11 */
+ ad_write(devc,10,54321);
+ if (ad_read(devc,11)!=54321) {
+ DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 3)\n"));
+ return(0);
+ }
+
+ /* writes to ireg 10 are copied to ireg 11 */
+ ad_write(devc,10,12345);
+ if (ad_read(devc,11)!=12345) {
+ DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 4)\n"));
+ return(0);
+ }
+
+ /* bit in base +1 cannot be set to 1 */
+ tmp=inb(devc->base+1);
+ outb(0xff,devc->base+1);
+ if (inb(devc->base+1)!=tmp) {
+ DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 5)\n"));
+ return(0);
+ }
+
+
+ DEBUGLOG (printk ("ad1816: detect() - Detected OK\n"));
+ DEBUGLOG (printk ("ad1816: AD1816 Version: %d\n",ad_read(devc,45)));
+
+ /* detection was successful */
+ return 1;
+}
+
+
+/* allocate resources from the kernel. If any allocation fails, free
+ all allocated resources and exit attach.
+
+ */
+
+void attach_ad1816 (struct address_info *hw_config)
+{
+ int my_dev;
+ char dev_name[100];
+ ad1816_info *devc = &dev_info[nr_ad1816_devs];
+
+
+ /* allocate i/o ports */
+ request_region (hw_config->io_base, 16, "AD1816 Sound");
+ devc->base = hw_config->io_base;
+
+ /* disable all interrupts */
+ ad_write(devc,1,0);
+
+ /* Clear pending interrupts */
+ outb (0, devc->base+1);
+
+ /* allocate irq */
+ if (hw_config->irq < 0 || hw_config->irq > 15) {
+ release_region(hw_config->io_base, 16);
+ return;
+ }
+ if (request_irq(hw_config->irq, ad1816_interrupt,0,
+ "SoundPort",
+ hw_config->osp) < 0) {
+ printk ("ad1816: IRQ in use\n");
+ release_region(hw_config->io_base, 16);
+ return;
+ }
+ devc->irq=hw_config->irq;
+
+ /* DMA stuff */
+ if (sound_alloc_dma (hw_config->dma, "Sound System")) {
+ printk ("ad1816: Can't allocate DMA%d\n", hw_config->dma);
+ free_irq(hw_config->irq,hw_config->osp);
+ release_region(hw_config->io_base, 16);
+ return;
+ }
+ devc->dma_playback=hw_config->dma;
+
+ if ( hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) {
+ if (sound_alloc_dma (hw_config->dma2, "Sound System (capture)")) {
+ printk ("ad1816: Can't allocate DMA%d\n", hw_config->dma2);
+ sound_free_dma(hw_config->dma);
+ free_irq(hw_config->irq,hw_config->osp);
+ release_region(hw_config->io_base, 16);
+ return;
+ }
+ devc->dma_capture=hw_config->dma2;
+ devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
+ } else {
+ devc->dma_capture=-1;
+ devc->audio_mode=DMA_AUTOMODE;
+ }
+
+ sprintf (dev_name,"AD1816 audio driver");
+
+ conf_printf2 (dev_name,
+ devc->base, devc->irq, hw_config->dma, hw_config->dma2);
+
+ /* register device */
+ if ((my_dev = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
+ dev_name,
+ &ad1816_audio_driver,
+ sizeof (struct audio_driver),
+ devc->audio_mode,
+ ad_format_mask,
+ devc,
+ hw_config->dma,
+ hw_config->dma2)) < 0) {
+ printk ("ad1816: Can't install sound driver\n");
+ if (devc->dma_capture>=0) {
+ sound_free_dma(hw_config->dma2);
+ }
+ sound_free_dma(hw_config->dma);
+ free_irq(hw_config->irq,hw_config->osp);
+ release_region(hw_config->io_base, 16);
+ return;
+
+ }
+
+ /* fill rest of structure with reasonable default values */
+ irq2dev[hw_config->irq] = devc->dev_no = my_dev;
+ devc->opened = 0;
+ devc->irq_ok = 0;
+ devc->osp = hw_config->osp;
+ nr_ad1816_devs++;
+
+ ad_write(devc,32,0x80f0); /* sound system mode */
+ ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
+ ad_write(devc,4,0x8080); /* default values for volumes (muted)*/
+ ad_write(devc,5,0x8080);
+ ad_write(devc,6,0x8080);
+ ad_write(devc,7,0x8080);
+ ad_write(devc,15,0x8888);
+ ad_write(devc,16,0x8888);
+ ad_write(devc,17,0x8888);
+ ad_write(devc,18,0x8888);
+ ad_write(devc,19,0xc888); /* +20db mic active */
+ ad_write(devc,14,0x0000); /* Master volume unmuted full power */
+ ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
+ ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
+ outb(0x10,devc->base+8); /* set dma mode */
+ outb(0x10,devc->base+9);
+
+ /* enable capture + playback interrupt */
+ ad_write(devc,1,0xc000);
+
+ /* set mixer defaults */
+ ad1816_mixer_reset (devc);
+
+ /* register mixer */
+ if ((audio_devs[my_dev]->mixer_dev=sound_install_mixer(
+ MIXER_DRIVER_VERSION,
+ dev_name,
+ &ad1816_mixer_operations,
+ sizeof (struct mixer_operations),
+ devc)) >= 0) {
+ audio_devs[my_dev]->min_fragment = 0;
+ }
+}
+
+void unload_card(ad1816_info *devc)
+{
+ int mixer, dev = 0;
+
+ if (devc != NULL) {
+ DEBUGLOG (printk("ad1816: Unloading card at base=%x\n",devc->base));
+
+ dev = devc->dev_no;
+ mixer = audio_devs[dev]->mixer_dev;
+
+ /* unreg mixer*/
+ if(mixer>=0) {
+ sound_unload_mixerdev(mixer);
+ }
+ sound_unload_audiodev(dev);
+
+ /* free dma channels */
+ if (devc->dma_capture>=0) {
+ sound_free_dma(devc->dma_capture);
+ }
+
+ /* card wont get added if resources could not be allocated
+ thus we need not ckeck if allocation was successful */
+ sound_free_dma (devc->dma_playback);
+ free_irq(devc->irq, devc->osp);
+ release_region (devc->base, 16);
+
+ DEBUGLOG (printk("ad1816: Unloading card at base=%x was successful\n",devc->base));
+
+ } else {
+ printk ("ad1816: no device/card specified\n");
+ }
+}
+
+void unload_ad1816 (struct address_info *hw_config)
+{
+ int i;
+ ad1816_info *devc = NULL;
+
+ /* remove any soundcard */
+ if (hw_config==NULL) {
+ for (i = 0; i < nr_ad1816_devs; i++) {
+ devc = &dev_info[i];
+ unload_card(devc);
+ }
+ nr_ad1816_devs=0;
+ } else {
+ /* remove specified soundcard */
+ for (i = 0; i < nr_ad1816_devs; i++) {
+ int j;
+
+ if (dev_info[i].base == hw_config->io_base) {
+ devc = &dev_info[i];
+ unload_card(devc);
+ nr_ad1816_devs--;
+ for ( j=i; j < nr_ad1816_devs ; j++) {
+ dev_info[j] = dev_info[j+1];
+ }
+ i--;
+ }
+ }
+ }
+}
+
+
+/* ----------------------------- 2.1.xxx module stuff ----------------- */
+
+EXPORT_SYMBOL(ad1816_interrupt);
+EXPORT_SYMBOL(probe_ad1816);
+EXPORT_SYMBOL(attach_ad1816);
+EXPORT_SYMBOL(unload_ad1816);
+
+
+#ifdef MODULE
+
+int io = -1;
+int irq = -1;
+int dma = -1;
+int dma2 = -1;
+
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma2,"i");
+MODULE_PARM(ad1816_clockfreq,"i");
+
+struct address_info cfg;
+
+
+int init_module(void)
+{
+ if (io == -1 || irq == -1 || dma == -1 || dma2 == -1) {
+ printk("ad1816: dma, dma2, irq and io must be set.\n");
+ return -EINVAL;
+ }
+ cfg.io_base = io;
+ cfg.irq = irq;
+ cfg.dma = dma;
+ cfg.dma2 = dma2;
+
+ if (probe_ad1816(&cfg) == 0) {
+ return -ENODEV;
+ }
+ attach_ad1816(&cfg);
+ SOUND_LOCK;
+ return 0;
+}
+
+
+void cleanup_module(void)
+{
+ unload_ad1816(NULL);
+ SOUND_LOCK_END;
+}
+
+#endif /* MODULE */
+
+#endif /* CONFIG_AD1816 */
diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c
index d3a743550..709d7f2ed 100644
--- a/drivers/sound/ad1848.c
+++ b/drivers/sound/ad1848.c
@@ -52,7 +52,7 @@ typedef struct
int dma1, dma2;
int dual_dma; /* 1, when two DMA channels allocated */
unsigned char MCE_bit;
- unsigned char saved_regs[16];
+ unsigned char saved_regs[32];
int debug_flag;
int audio_flags;
@@ -71,6 +71,7 @@ typedef struct
#define MD_4232 5
#define MD_C930 6
#define MD_IWAVE 7
+#define MD_4235 8 /* Crystal Audio CS4235 */
/* Mixer parameters */
int recmask;
@@ -111,7 +112,7 @@ static int timer_installed = -1;
#endif
-static int ad_format_mask[8 /*devc->model */ ] =
+static int ad_format_mask[9 /*devc->model */ ] =
{
0,
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW,
@@ -120,7 +121,8 @@ static int ad_format_mask[8 /*devc->model */ ] =
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW, /* AD1845 */
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
- AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM
+ AFMT_U8 | AFMT_S16_LE | AFMT_MU_LAW | AFMT_A_LAW | AFMT_S16_BE | AFMT_IMA_ADPCM,
+ AFMT_U8 | AFMT_S16_LE /* CS4235 */
};
static ad1848_info adev_info[MAX_AUDIO_DEV];
@@ -442,10 +444,6 @@ static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
left = mix_cvt[left];
right = mix_cvt[right];
- /* Scale it again */
- left = mix_cvt[left];
- right = mix_cvt[right];
-
if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
return -EINVAL;
@@ -1205,15 +1203,17 @@ static void ad1848_halt_input(int dev)
{
int tmout;
-
- disable_dma(audio_devs[dev]->dmap_in->dma);
+
+ if(!isa_dma_bridge_buggy)
+ disable_dma(audio_devs[dev]->dmap_in->dma);
for (tmout = 0; tmout < 100000; tmout++)
if (ad_read(devc, 11) & 0x10)
break;
ad_write(devc, 9, ad_read(devc, 9) & ~0x02); /* Stop capture */
- enable_dma(audio_devs[dev]->dmap_in->dma);
+ if(!isa_dma_bridge_buggy)
+ enable_dma(audio_devs[dev]->dmap_in->dma);
devc->audio_mode &= ~PCM_ENABLE_INPUT;
}
@@ -1240,14 +1240,17 @@ static void ad1848_halt_output(int dev)
{
int tmout;
- disable_dma(audio_devs[dev]->dmap_out->dma);
+ if(!isa_dma_bridge_buggy)
+ disable_dma(audio_devs[dev]->dmap_out->dma);
for (tmout = 0; tmout < 100000; tmout++)
if (ad_read(devc, 11) & 0x10)
break;
ad_write(devc, 9, ad_read(devc, 9) & ~0x01); /* Stop playback */
- enable_dma(audio_devs[dev]->dmap_out->dma);
+ if(!isa_dma_bridge_buggy)
+ enable_dma(audio_devs[dev]->dmap_out->dma);
+
devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
}
@@ -1593,103 +1596,110 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
ad_write(devc, 25, ~tmp1); /* Invert all bits */
if ((ad_read(devc, 25) & 0xe7) == (tmp1 & 0xe7))
{
- int id, full_id;
+ int id;
/*
* It's at least CS4231
*/
-
+
devc->chip_name = "CS4231";
devc->model = MD_4231;
-
+
/*
* It could be an AD1845 or CS4231A as well.
* CS4231 and AD1845 report the same revision info in I25
* while the CS4231A reports different.
*/
- id = ad_read(devc, 25) & 0xe7;
- full_id = ad_read(devc, 25);
- if (id == 0x80) /* Device busy??? */
- id = ad_read(devc, 25) & 0xe7;
- if (id == 0x80) /* Device still busy??? */
- id = ad_read(devc, 25) & 0xe7;
+ id = ad_read(devc, 25);
+ if ((id & 0xe7) == 0x80) /* Device busy??? */
+ id = ad_read(devc, 25);
+ if ((id & 0xe7) == 0x80) /* Device still busy??? */
+ id = ad_read(devc, 25);
DDB(printk("ad1848_detect() - step J (%02x/%02x)\n", id, ad_read(devc, 25)));
- switch (id)
+ if ((id & 0xe7) == 0x80) {
+ /*
+ * It must be a CS4231 or AD1845. The register I23 of
+ * CS4231 is undefined and it appears to be read only.
+ * AD1845 uses I23 for setting sample rate. Assume
+ * the chip is AD1845 if I23 is changeable.
+ */
+
+ unsigned char tmp = ad_read(devc, 23);
+ ad_write(devc, 23, ~tmp);
+
+ if (interwave)
+ {
+ devc->model = MD_IWAVE;
+ devc->chip_name = "IWave";
+ }
+ else if (ad_read(devc, 23) != tmp) /* AD1845 ? */
+ {
+ devc->chip_name = "AD1845";
+ devc->model = MD_1845;
+ }
+ else if (cs4248_flag)
+ {
+ if (ad_flags)
+ *ad_flags |= AD_F_CS4248;
+ devc->chip_name = "CS4248";
+ devc->model = MD_1848;
+ ad_write(devc, 12, ad_read(devc, 12) & ~0x40); /* Mode2 off */
+ }
+ ad_write(devc, 23, tmp); /* Restore */
+ }
+ else
{
-
- case 0xa0:
- devc->chip_name = "CS4231A";
- devc->model = MD_4231A;
+ switch (id & 0x1f) {
+ case 3: /* CS4236/CS4235 */
+ {
+ int xid;
+ ad_write(devc, 12, ad_read(devc, 12) | 0x60); /* switch to mode 3 */
+ ad_write(devc, 23, 0x9c); /* select extended register 25 */
+ xid = inb(io_Indexed_Data(devc));
+ ad_write(devc, 12, ad_read(devc, 12) & ~0x60); /* back to mode 0 */
+ if ((xid & 0x1f) == 0x1d) {
+ devc->chip_name = "CS4235";
+ devc->model = MD_4235;
+ } else {
+ devc->chip_name = "CS4236";
+ devc->model = MD_4232;
+ }
+ }
break;
- case 0xa2:
+ case 2: /* CS4232/CS4232A */
devc->chip_name = "CS4232";
devc->model = MD_4232;
break;
-
- case 0xb2:
- devc->chip_name = "CS4232A";
- devc->model = MD_4232;
- break;
-
- case 0x03:
- case 0x83:
- devc->chip_name = "CS4236";
- devc->model = MD_4232;
- break;
-
- case 0x41:
- devc->chip_name = "CS4236B";
- devc->model = MD_4232;
- break;
-
- case 0x80:
+
+ case 0:
+ if ((id & 0xe0) == 0xa0)
{
- /*
- * It must be a CS4231 or AD1845. The register I23 of
- * CS4231 is undefined and it appears to be read only.
- * AD1845 uses I23 for setting sample rate. Assume
- * the chip is AD1845 if I23 is changeable.
- */
-
- unsigned char tmp = ad_read(devc, 23);
- ad_write(devc, 23, ~tmp);
-
- if (interwave)
- {
- devc->model = MD_IWAVE;
- devc->chip_name = "IWave";
- }
- else if (ad_read(devc, 23) != tmp) /* AD1845 ? */
- {
- devc->chip_name = "AD1845";
- devc->model = MD_1845;
- }
- else if (cs4248_flag)
- {
- if (ad_flags)
- *ad_flags |= AD_F_CS4248;
- devc->chip_name = "CS4248";
- devc->model = MD_1848;
- ad_write(devc, 12, ad_read(devc, 12) & ~0x40); /* Mode2 off */
- }
- ad_write(devc, 23, tmp); /* Restore */
+ devc->chip_name = "CS4231A";
+ devc->model = MD_4231A;
+ }
+ else
+ {
+ devc->chip_name = "CS4321";
+ devc->model = MD_4231;
}
break;
- default: /* Assume CS4231 or OPTi 82C930 */
+ default: /* maybe */
DDB(printk("ad1848: I25 = %02x/%02x\n", ad_read(devc, 25), ad_read(devc, 25) & 0xe7));
- if (optiC930)
- {
- devc->chip_name = "82C930";
- devc->model = MD_C930;
- }
+ if (optiC930)
+ {
+ devc->chip_name = "82C930";
+ devc->model = MD_C930;
+ }
else
{
+ devc->chip_name = "CS4231";
devc->model = MD_4231;
}
+ }
}
}
ad_write(devc, 25, tmp1); /* Restore bits */
@@ -1937,10 +1947,11 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */
free_irq(devc->irq, (void *)devc->dev_no);
- sound_free_dma(audio_devs[dev]->dmap_out->dma);
+ sound_free_dma(dma_playback);
+
+ if (dma_playback != dma_capture)
+ sound_free_dma(dma_capture);
- if (audio_devs[dev]->dmap_in->dma != audio_devs[dev]->dmap_out->dma)
- sound_free_dma(audio_devs[dev]->dmap_in->dma);
}
mixer = audio_devs[devc->dev_no]->mixer_dev;
if(mixer>=0)
@@ -2287,7 +2298,8 @@ int probe_ms_sound(struct address_info *hw_config)
hw_config->card_subtype = 1;
return 1;
}
- if ((hw_config->irq != 7) &&
+ if ((hw_config->irq != 5) &&
+ (hw_config->irq != 7) &&
(hw_config->irq != 9) &&
(hw_config->irq != 10) &&
(hw_config->irq != 11))
@@ -2321,7 +2333,7 @@ void attach_ms_sound(struct address_info *hw_config)
{
static char interrupt_bits[12] =
{
- -1, -1, -1, -1, -1, -1, -1, 0x08, -1, 0x10, 0x18, 0x20
+ -1, -1, -1, -1, -1, 0x00, -1, 0x08, -1, 0x10, 0x18, 0x20
};
char bits, dma2_bit = 0;
@@ -2408,7 +2420,7 @@ void unload_ms_sound(struct address_info *hw_config)
ad1848_unload(hw_config->io_base + 4,
hw_config->irq,
hw_config->dma,
- hw_config->dma, 0);
+ hw_config->dma2, 0);
sound_unload_audiodev(hw_config->slots[0]);
release_region(hw_config->io_base, 4);
}
diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c
index 286eca011..605a03ba5 100644
--- a/drivers/sound/audio.c
+++ b/drivers/sound/audio.c
@@ -199,6 +199,9 @@ int audio_write(int dev, struct file *file, const char *buf, int count)
p = 0;
c = count;
+
+ if(count < 0)
+ return -EINVAL;
if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
return -EPERM;
@@ -810,8 +813,10 @@ int dma_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
reorganize_buffers(dev, dmap_in, 1);
if ((err = audio_devs[dev]->d->prepare_for_input(dev,
- dmap_in->fragment_size, dmap_in->nbufs)) < 0)
+ dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
+ restore_flags(flags);
return -err;
+ }
dmap_in->dma_mode = DMODE_INPUT;
audio_devs[dev]->enable_bits = bits;
DMAbuf_activate_recording(dev, dmap_in);
diff --git a/drivers/sound/cs4232.c b/drivers/sound/cs4232.c
index 122b0198f..11feddccc 100644
--- a/drivers/sound/cs4232.c
+++ b/drivers/sound/cs4232.c
@@ -63,9 +63,7 @@ static void CS_OUT(unsigned char a)
#define CS_OUT3(a, b, c) {CS_OUT(a);CS_OUT(b);CS_OUT(c);}
static int mpu_base = 0, mpu_irq = 0;
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
static int synth_base = 0, synth_irq = 0;
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
static int mpu_detected = 0;
int probe_cs4232_mpu(struct address_info *hw_config)
@@ -188,7 +186,7 @@ int probe_cs4232(struct address_info *hw_config)
}
#endif
-#if defined(CONFIG_SOUND_WAVEFRONT) || defined(CONFIG_SOUND_WAVEFRONT_MODULE)
+ if(synth_base != 0)
{
CS_OUT2 (0x15, 0x04); /* logical device 4 (WaveFront) */
CS_OUT3 (0x47, (synth_base >> 8) & 0xff,
@@ -196,7 +194,7 @@ int probe_cs4232(struct address_info *hw_config)
CS_OUT2 (0x22, synth_irq); /* IRQ */
CS_OUT2 (0x33, 0x01); /* Activate logical dev 4 */
}
-#endif
+
/*
* Finally activate the chip
*/
@@ -331,12 +329,10 @@ MODULE_PARM(dma2,"i");
MODULE_PARM(mpuio,"i");
MODULE_PARM(mpuirq,"i");
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
int synthio = -1;
int synthirq = -1;
MODULE_PARM(synthio,"i");
MODULE_PARM(synthirq,"i");
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
EXPORT_NO_SYMBOLS;
@@ -350,51 +346,45 @@ struct address_info mpu_cfg;
int init_module(void)
{
-
-#ifndef CONFIG_SOUND_WAVEFRONT_MODULE
-
if (io == -1 || irq == -1 || dma == -1 || dma2 == -1)
{
printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n");
return -EINVAL;
}
-#else
- if (synthio == -1 || synthirq == -1 ||
- io == -1 || irq == -1 || dma == -1 || dma2 == -1)
+#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
+ if(synthio == -1)
+ printk(KERN_WARNING "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
+ else
{
- printk(KERN_ERR "cs4232: synthio, synthirq, dma, dma2, "
- "irq and io must be set.\n");
- return -EINVAL;
+ synth_base = synthio;
+ synth_irq = synthirq;
}
-
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
+#else
+ if(synthio != -1)
+ printk(KERN_WARNING "cs4232: wavefront support not enabled in this driver.\n");
+#endif
cfg.io_base = io;
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma2;
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
- synth_base = synthio;
- synth_irq = synthirq;
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
-
- if (probe_cs4232(&cfg) == 0)
- return -ENODEV;
-
mpu_cfg.io_base = -1;
mpu_cfg.irq = -1;
if (mpuio != -1 && mpuirq != -1) {
- mpu_cfg.io_base = mpuio;
- mpu_cfg.irq = mpuirq;
- probe_cs4232_mpu(&mpu_cfg); /* Bug always returns 0 not OK -- AC */
+ mpu_cfg.io_base = mpuio;
+ mpu_cfg.irq = mpuirq;
+ probe_cs4232_mpu(&mpu_cfg); /* Bug always returns 0 not OK -- AC */
}
+ if (probe_cs4232(&cfg) == 0)
+ return -ENODEV;
+
attach_cs4232(&cfg);
if (mpuio != -1 && mpuirq != -1) {
- attach_cs4232_mpu(&mpu_cfg);
+ attach_cs4232_mpu(&mpu_cfg);
}
SOUND_LOCK;
diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c
index 7e5c4b76c..9a6b4c72f 100644
--- a/drivers/sound/dev_table.c
+++ b/drivers/sound/dev_table.c
@@ -524,7 +524,7 @@ void sound_unload_audiodev(int dev)
int sound_alloc_audiodev(void)
{
- int i = register_sound_dsp(&oss_sound_fops);
+ int i = register_sound_dsp(&oss_sound_fops, -1);
if(i==-1)
return i;
i>>=4;
@@ -536,7 +536,7 @@ int sound_alloc_audiodev(void)
int sound_alloc_mididev(void)
{
#ifdef CONFIG_MIDI
- int i = register_sound_midi(&oss_sound_fops);
+ int i = register_sound_midi(&oss_sound_fops, -1);
if(i==-1)
return i;
i>>=4;
@@ -566,7 +566,7 @@ int sound_alloc_synthdev(void)
int sound_alloc_mixerdev(void)
{
- int i = register_sound_mixer(&oss_sound_fops);
+ int i = register_sound_mixer(&oss_sound_fops, -1);
if(i==-1)
return -1;
i>>=4;
diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h
index b440f3c09..019b915c5 100644
--- a/drivers/sound/dev_table.h
+++ b/drivers/sound/dev_table.h
@@ -33,6 +33,8 @@
#define SNDCARD_WAVEFRONT 41
#define SNDCARD_OPL3SA2 42
#define SNDCARD_OPL3SA2_MPU 43
+#define SNDCARD_WAVEARTIST 44
+#define SNDCARD_AD1816 88
void attach_opl3sa_wss (struct address_info *hw_config);
int probe_opl3sa_wss (struct address_info *hw_config);
@@ -202,6 +204,7 @@ struct audio_driver
short (*set_channels)(int dev, short channels);
void (*postprocess_write)(int dev); /* Device spesific postprocessing for written data */
void (*preprocess_read)(int dev); /* Device spesific preprocessing for read data */
+ void (*mmap)(int dev);
};
struct audio_operations
@@ -427,6 +430,11 @@ struct driver_info sound_drivers[] =
{"SGALAXY", 0, SNDCARD_SGALAXY, "Sound Galaxy WSS", attach_sgalaxy, probe_sgalaxy, unload_sgalaxy},
#endif
+#ifdef CONFIG_SOUND_AD1816
+ {"AD1816", 0, SNDCARD_AD1816, "AD1816", attach_ad1816,
+probe_ad1816, unload_ad1816},
+#endif
+
#ifdef CONFIG_SOUND_YM3812
{"OPL3", 0, SNDCARD_ADLIB, "OPL-2/OPL-3 FM", attach_adlib_card, probe_adlib, unload_adlib},
#endif
@@ -493,9 +501,12 @@ struct driver_info sound_drivers[] =
#if defined(CONFIG_SOUND_VMIDI) && defined(CONFIG_MIDI)
{"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device", attach_v_midi, probe_v_midi, unload_v_midi},
#endif
-#ifdef CONFIG_VIDC_SOUND
+#ifdef CONFIG_SOUND_VIDC
{"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc },
#endif
+#ifdef CONFIG_SOUND_WAVEARTIST
+ {"WaveArtist", 0, SNDCARD_WAVEARTIST, "NetWinder WaveArtist", attach_waveartist, probe_waveartist, unload_waveartist },
+#endif
{NULL, 0, 0, "*?*", NULL, NULL, NULL}
};
@@ -668,9 +679,13 @@ struct card_info snd_installed_cards[] =
{SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE},
#endif
-#ifdef CONFIG_VIDC_SOUND
+#ifdef CONFIG_SOUND_VIDC
{ SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE },
#endif
+
+#ifdef CONFIG_SOUND_WAVEARTIST
+ { SNDCARD_WAVEARTIST, { CONFIG_WAVEARTIST_BASE, CONFIG_WAVEARTIST_IRQ, CONFIG_WAVEARTIST_DMA, CONFIG_WAVEARTIST_DMA2 }, SND_DEFAULT_ENABLE },
+#endif
{0, {0}, 0}
};
diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c
index 014d6a73c..ccde8519a 100644
--- a/drivers/sound/dmabuf.c
+++ b/drivers/sound/dmabuf.c
@@ -474,7 +474,7 @@ int DMAbuf_release(int dev, int mode)
adev->dmap_in->closing = 1;
if (adev->open_mode & OPEN_WRITE)
- if (!(adev->dmap_in->mapping_flags & DMA_MAP_MAPPED))
+ if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED))
if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT))
DMAbuf_sync(dev);
if (adev->dmap_out->dma_mode == DMODE_OUTPUT)
@@ -630,7 +630,10 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
f=claim_dma_lock();
clear_dma_ff(chan);
- disable_dma(dmap->dma);
+
+ if(!isa_dma_bridge_buggy)
+ disable_dma(dmap->dma);
+
pos = get_dma_residue(chan);
pos = dmap->bytes_in_use - pos;
@@ -650,7 +653,10 @@ int DMAbuf_get_buffer_pointer(int dev, struct dma_buffparms *dmap, int direction
pos = 0;
if (pos >= dmap->bytes_in_use)
pos = 0;
- enable_dma(dmap->dma);
+
+ if(!isa_dma_bridge_buggy)
+ enable_dma(dmap->dma);
+
release_dma_lock(f);
}
restore_flags(flags);
@@ -727,7 +733,7 @@ static int output_sleep(int dev, int dontblock)
struct audio_operations *adev = audio_devs[dev];
int err = 0;
struct dma_buffparms *dmap = adev->dmap_out;
- int timeout;
+ long timeout;
long timeout_value;
if (dontblock)
@@ -1016,10 +1022,13 @@ void DMAbuf_outputintr(int dev, int notify_only)
unsigned long f;
f=claim_dma_lock();
- disable_dma(dmap->dma);
+
+ if(!isa_dma_bridge_buggy)
+ disable_dma(dmap->dma);
clear_dma_ff(chan);
pos = dmap->bytes_in_use - get_dma_residue(chan);
- enable_dma(dmap->dma);
+ if(!isa_dma_bridge_buggy)
+ enable_dma(dmap->dma);
release_dma_lock(f);
pos = pos / dmap->fragment_size; /* Actual qhead */
@@ -1111,10 +1120,12 @@ void DMAbuf_inputintr(int dev)
unsigned long f;
f=claim_dma_lock();
- disable_dma(dmap->dma);
+ if(!isa_dma_bridge_buggy)
+ disable_dma(dmap->dma);
clear_dma_ff(chan);
pos = dmap->bytes_in_use - get_dma_residue(chan);
- enable_dma(dmap->dma);
+ if(!isa_dma_bridge_buggy)
+ enable_dma(dmap->dma);
release_dma_lock(f);
pos = pos / dmap->fragment_size; /* Actual qhead */
diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c
index aaf21e2ba..43b419817 100644
--- a/drivers/sound/dmasound.c
+++ b/drivers/sound/dmasound.c
@@ -90,7 +90,7 @@ History:
#include <linux/sound.h>
#include <linux/init.h>
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
#include <asm/setup.h>
#endif
#include <asm/system.h>
@@ -686,9 +686,9 @@ static struct sound_settings sound;
#ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags) __init;
-static void AtaFree(void *, unsigned int size) __init;
-static int AtaIrqInit(void) __init;
+static void *AtaAlloc(unsigned int size, int flags);
+static void AtaFree(void *, unsigned int size);
+static int AtaIrqInit(void);
#ifdef MODULE
static void AtaIrqCleanUp(void);
#endif /* MODULE */
@@ -709,9 +709,9 @@ static void ata_sq_interrupt(int irq, void *dummy, struct pt_regs *fp);
#endif /* CONFIG_ATARI */
#ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags) __init;
-static void AmiFree(void *, unsigned int) __init;
-static int AmiIrqInit(void) __init;
+static void *AmiAlloc(unsigned int size, int flags);
+static void AmiFree(void *, unsigned int);
+static int AmiIrqInit(void);
#ifdef MODULE
static void AmiIrqCleanUp(void);
#endif /* MODULE */
@@ -726,9 +726,9 @@ static void ami_sq_interrupt(int irq, void *dummy, struct pt_regs *fp);
#endif /* CONFIG_AMIGA */
#ifdef CONFIG_PPC
-static void *PMacAlloc(unsigned int size, int flags) __init;
-static void PMacFree(void *ptr, unsigned int size) __init;
-static int PMacIrqInit(void) __init;
+static void *PMacAlloc(unsigned int size, int flags);
+static void PMacFree(void *ptr, unsigned int size);
+static int PMacIrqInit(void);
#ifdef MODULE
static void PMacIrqCleanup(void);
#endif /* MODULE */
@@ -2084,8 +2084,7 @@ static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount,
int utotal, ftotal;
frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
+ userCount >>= (stereo? 2: 1);
ftotal = frameLeft;
utotal = userCount;
while (frameLeft) {
@@ -2130,8 +2129,7 @@ static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount,
int utotal, ftotal;
frameLeft >>= 2;
- if (stereo)
- userCount >>= 1;
+ userCount >>= (stereo? 2: 1);
ftotal = frameLeft;
utotal = userCount;
while (frameLeft) {
@@ -2223,7 +2221,7 @@ static void AtaFree(void *obj, unsigned int size)
atari_stram_free( obj );
}
-static int AtaIrqInit(void)
+static int __init AtaIrqInit(void)
{
/* Set up timer A. Timer A
will receive a signal upon end of playing from the sound
@@ -2720,7 +2718,7 @@ static void AmiFree(void *obj, unsigned int size)
amiga_chip_free (obj);
}
-static int AmiIrqInit(void)
+static int __init AmiIrqInit(void)
{
/* turn off DMA for audio channels */
custom.dmacon = AMI_AUDIO_OFF;
@@ -2988,7 +2986,7 @@ static void PMacFree(void *ptr, unsigned int size)
kfree(ptr);
}
-static int PMacIrqInit(void)
+static int __init PMacIrqInit(void)
{
if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0)
|| request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0))
@@ -3850,12 +3848,12 @@ static struct file_operations mixer_fops =
};
-__initfunc(static void mixer_init(void))
+static void __init mixer_init(void)
{
#ifndef MODULE
int mixer_unit;
#endif
- mixer_unit = register_sound_mixer(&mixer_fops);
+ mixer_unit = register_sound_mixer(&mixer_fops, -1);
if (mixer_unit < 0)
return;
@@ -3898,6 +3896,42 @@ __initfunc(static void mixer_init(void))
*/
+static int sq_allocate_buffers(void)
+{
+ int i;
+
+ if (sound_buffers)
+ return 0;
+ sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
+ if (!sound_buffers)
+ return -ENOMEM;
+ for (i = 0; i < numBufs; i++) {
+ sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
+ if (!sound_buffers[i]) {
+ while (i--)
+ sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+ kfree (sound_buffers);
+ sound_buffers = 0;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+
+static void sq_release_buffers(void)
+{
+ int i;
+
+ if (sound_buffers) {
+ for (i = 0; i < numBufs; i++)
+ sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+ kfree (sound_buffers);
+ sound_buffers = 0;
+ }
+}
+
+
static void sq_setup(int numBufs, int bufSize, char **buffers)
{
#ifdef CONFIG_PPC
@@ -3913,7 +3947,6 @@ static void sq_setup(int numBufs, int bufSize, char **buffers)
sq.front = sq.count = 0;
sq.rear = -1;
sq.write_queue = sq.open_queue = sq.sync_queue = 0;
- sq.busy = 0;
sq.syncing = 0;
sq.playing = 0;
@@ -4033,9 +4066,12 @@ static int sq_open(struct inode *inode, struct file *file)
}
rc = 0;
}
+ sq.busy = 1;
+ rc = sq_allocate_buffers();
+ if (rc)
+ goto err_out_nobusy;
sq_setup(numBufs, bufSize << 10, sound_buffers);
sq.open_mode = file->f_flags;
- sq.busy = 1;
#ifdef CONFIG_ATARI
sq.ignore_int = 1;
#endif /* CONFIG_ATARI */
@@ -4049,6 +4085,9 @@ static int sq_open(struct inode *inode, struct file *file)
sound_set_format(AFMT_MU_LAW);
}
return 0;
+err_out_nobusy:
+ sq.busy = 0;
+ WAKE_UP(sq.open_queue);
err_out:
MOD_DEC_USE_COUNT;
return rc;
@@ -4101,8 +4140,10 @@ static int sq_release(struct inode *inode, struct file *file)
sound.soft = sound.dsp;
sound.hard = sound.dsp;
sound_silence();
- if (rc == 0)
+ if (rc == 0) {
+ sq_release_buffers();
MOD_DEC_USE_COUNT;
+ }
return rc;
}
@@ -4212,12 +4253,12 @@ static struct file_operations sq_fops =
};
-__initfunc(static void sq_init(void))
+static void __init sq_init(void)
{
#ifndef MODULE
int sq_unit;
#endif
- sq_unit = register_sound_dsp(&sq_fops);
+ sq_unit = register_sound_dsp(&sq_fops, -1);
if (sq_unit < 0)
return;
@@ -4407,7 +4448,7 @@ static struct file_operations state_fops =
};
-__initfunc(static void state_init(void))
+static void __init state_init(void)
{
#ifndef MODULE
int state_unit;
@@ -4430,15 +4471,14 @@ static long long sound_lseek(struct file *file, long long offset, int orig)
/*** Config & Setup **********************************************************/
-__initfunc(void dmasound_init(void))
+void __init dmasound_init(void)
{
int has_sound = 0;
- int i;
#ifdef CONFIG_PPC
struct device_node *np;
#endif
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
switch (m68k_machtype) {
#ifdef CONFIG_ATARI
case MACH_ATARI:
@@ -4466,7 +4506,7 @@ __initfunc(void dmasound_init(void))
break;
#endif /* CONFIG_AMIGA */
}
-#endif /* __mc68000__ */
+#endif /* __mc68000__||CONFIG_APUS */
#ifdef CONFIG_PPC
awacs_subframe = 0;
@@ -4501,8 +4541,10 @@ __initfunc(void dmasound_init(void))
awacs_rx_irq = np->intrs[2].line;
awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd),
GFP_KERNEL);
- if (awacs_tx_cmd_space == NULL)
- goto out_of_memory;
+ if (awacs_tx_cmd_space == NULL) {
+ printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
+ return;
+ }
awacs_tx_cmds = (volatile struct dbdma_cmd *)
DBDMA_ALIGN(awacs_tx_cmd_space);
awacs_reg[0] = MASK_MUX_CD;
@@ -4543,24 +4585,6 @@ __initfunc(void dmasound_init(void))
return;
/* Set up sound queue, /dev/audio and /dev/dsp. */
- sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
- if (!sound_buffers) {
- out_of_memory:
- printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
- return;
- }
- for (i = 0; i < numBufs; i++) {
- sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
- if (!sound_buffers[i]) {
- while (i--)
- sound.mach.dma_free (sound_buffers[i], bufSize << 10);
- kfree (sound_buffers);
- sound_buffers = 0;
- goto out_of_memory;
- }
- }
-
- sq_setup(numBufs, bufSize << 10, sound_buffers);
/* Set default settings. */
sq_init();
@@ -4588,7 +4612,7 @@ __initfunc(void dmasound_init(void))
#define MAXARGS 8 /* Should be sufficient for now */
-__initfunc(void dmasound_setup(char *str, int *ints))
+void __init dmasound_setup(char *str, int *ints)
{
/* check the bootstrap parameter for "dmasound=" */
@@ -4628,18 +4652,12 @@ int init_module(void)
void cleanup_module(void)
{
- int i;
-
if (irq_installed) {
sound_silence();
sound.mach.irqcleanup();
}
- if (sound_buffers) {
- for (i = 0; i < numBufs; i++)
- sound.mach.dma_free(sound_buffers[i], bufSize << 10);
- kfree(sound_buffers);
- }
+ sq_release_buffers();
if (mixer_unit >= 0)
unregister_sound_mixer(mixer_unit);
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index f7dd0c8a3..37d1fc38f 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -79,6 +79,10 @@
* 31.08.98 0.13 Fix realplayer problems - dac.count issues
* 08.10.98 0.14 Joystick support fixed
* -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
+ * 10.12.98 0.15 Fix drain_dac trying to wait on not yet initialized DMA
+ * 16.12.98 0.16 Don't wake up app until there are fragsize bytes to read/write
+ * 06.01.99 0.17 remove the silly SA_INTERRUPT flag.
+ * hopefully killed the egcs section type conflict
*
* some important things missing in Ensoniq documentation:
*
@@ -602,17 +606,14 @@ static void es1370_update_ptr(struct es1370_state *s)
diff = get_hwptr(s, &s->dma_adc, ES1370_REG_ADC_FRAMECNT);
s->dma_adc.total_bytes += diff;
s->dma_adc.count += diff;
- if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- wake_up(&s->dma_adc.wait);
- } else {
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+ wake_up(&s->dma_adc.wait);
+ if (!s->dma_adc.mapped) {
if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
s->ctrl &= ~CTRL_ADC_EN;
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
s->dma_adc.error++;
}
- if (s->dma_adc.count > 0)
- wake_up(&s->dma_adc.wait);
}
}
/* update DAC1 pointer */
@@ -634,7 +635,7 @@ static void es1370_update_ptr(struct es1370_state *s)
s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80);
s->dma_dac1.endcleared = 1;
}
- if (s->dma_dac1.count < (signed)s->dma_dac1.dmasize)
+ if (s->dma_dac1.count + (signed)s->dma_dac1.fragsize <= (signed)s->dma_dac1.dmasize)
wake_up(&s->dma_dac1.wait);
}
}
@@ -657,7 +658,7 @@ static void es1370_update_ptr(struct es1370_state *s)
s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80);
s->dma_dac2.endcleared = 1;
}
- if (s->dma_dac2.count < (signed)s->dma_dac2.dmasize)
+ if (s->dma_dac2.count + (signed)s->dma_dac2.fragsize <= (signed)s->dma_dac2.dmasize)
wake_up(&s->dma_dac2.wait);
}
}
@@ -998,7 +999,7 @@ static int drain_dac1(struct es1370_state *s, int nonblock)
unsigned long flags;
int count, tmo;
- if (s->dma_dac1.mapped)
+ if (s->dma_dac1.mapped || !s->dma_dac1.ready)
return 0;
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1033,7 +1034,7 @@ static int drain_dac2(struct es1370_state *s, int nonblock)
unsigned long flags;
int count, tmo;
- if (s->dma_dac2.mapped)
+ if (s->dma_dac2.mapped || !s->dma_dac2.ready)
return 0;
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&s->dma_dac2.wait, &wait);
@@ -1185,20 +1186,15 @@ static unsigned int es1370_poll(struct file *file, struct poll_table_struct *wai
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
if (file->f_mode & FMODE_READ) {
- if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- mask |= POLLIN | POLLRDNORM;
- } else {
- if (s->dma_adc.count > 0)
- mask |= POLLIN | POLLRDNORM;
- }
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+ mask |= POLLIN | POLLRDNORM;
}
if (file->f_mode & FMODE_WRITE) {
if (s->dma_dac2.mapped) {
if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if ((signed)s->dma_dac2.dmasize > s->dma_dac2.count)
+ if ((signed)s->dma_dac2.dmasize >= s->dma_dac2.count + (signed)s->dma_dac2.fragsize)
mask |= POLLOUT | POLLWRNORM;
}
}
@@ -1703,7 +1699,7 @@ static unsigned int es1370_poll_dac(struct file *file, struct poll_table_struct
if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if ((signed)s->dma_dac1.dmasize > s->dma_dac1.count)
+ if ((signed)s->dma_dac1.dmasize >= s->dma_dac1.count + (signed)s->dma_dac1.fragsize)
mask |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&s->lock, flags);
@@ -2247,7 +2243,7 @@ static int micz[NR_DEVICE] = { 0, };
/* --------------------------------------------------------------------- */
-static const struct initvol {
+static struct initvol {
int mixch;
int vol;
} initvol[] __initdata = {
@@ -2276,7 +2272,7 @@ __initfunc(int init_es1370(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.13 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.17 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
if (pcidev->base_address[0] == 0 ||
@@ -2304,7 +2300,7 @@ __initfunc(int init_es1370(void))
goto err_region;
}
request_region(s->io, ES1370_EXTENT, "es1370");
- if (request_irq(s->irq, es1370_interrupt, SA_INTERRUPT|SA_SHIRQ, "es1370", s)) {
+ if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
goto err_irq;
}
@@ -2327,13 +2323,13 @@ __initfunc(int init_es1370(void))
(s->ctrl & CTRL_XCTL0) ? "out" : "in",
(s->ctrl & CTRL_XCTL1) ? "1" : "0");
/* register devices */
- if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops)) < 0)
+ if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0)
goto err_dev1;
- if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops)) < 0)
+ if ((s->dev_mixer = register_sound_mixer(&es1370_mixer_fops, -1)) < 0)
goto err_dev2;
- if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops)) < 0)
+ if ((s->dev_dac = register_sound_dsp(&es1370_dac_fops, -1)) < 0)
goto err_dev3;
- if ((s->dev_midi = register_sound_midi(&es1370_midi_fops)) < 0)
+ if ((s->dev_midi = register_sound_midi(&es1370_midi_fops, -1)) < 0)
goto err_dev4;
/* initialize the chips */
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
@@ -2401,8 +2397,6 @@ void cleanup_module(void)
synchronize_irq();
free_irq(s->irq, s);
release_region(s->io, ES1370_EXTENT);
- if (s->ctrl & CTRL_JYSTK_EN)
- release_region(0x200, JOY_EXTENT);
unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->dev_mixer);
unregister_sound_dsp(s->dev_dac);
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index 754aa443b..e52f47d14 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -23,12 +23,10 @@
*
*
* Module command line parameters:
- * joystick if 1 enables the joystick interface on the card; but it still
- * needs a separate joystick driver (presumably PC standard, although
- * the chip doc doesn't say anything and it looks slightly fishy from
- * the PCI standpoint...)
- *
- *
+ * joystick must be set to the base I/O-Port to be used for
+ * the gameport. Legal values are 0x200, 0x208, 0x210 and 0x218.
+ * The gameport is mirrored eight times.
+ *
* Supported devices:
* /dev/dsp standard /dev/dsp device, (mostly) OSS compatible
* /dev/mixer standard /dev/mixer device, (mostly) OSS compatible
@@ -49,11 +47,19 @@
* Now mixer behaviour can basically be selected between
* "OSS documented" and "OSS actual" behaviour
* 31.08.98 0.4 Fix realplayer problems - dac.count issues
+ * 27.10.98 0.5 Fix joystick support
+ * -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
+ * 10.12.98 0.6 Fix drain_dac trying to wait on not yet initialized DMA
+ * 23.12.98 0.7 Fix a few f_file & FMODE_ bugs
+ * Don't wake up app until there are fragsize bytes to read/write
+ * 06.01.99 0.8 remove the silly SA_INTERRUPT flag.
+ * hopefully killed the egcs section type conflict
*
*/
/*****************************************************************************/
+#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/string.h>
@@ -835,17 +841,14 @@ static void es1371_update_ptr(struct es1371_state *s)
diff = get_hwptr(s, &s->dma_adc, ES1371_REG_ADC_FRAMECNT);
s->dma_adc.total_bytes += diff;
s->dma_adc.count += diff;
- if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= s->dma_adc.fragsize)
- wake_up(&s->dma_adc.wait);
- } else {
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+ wake_up(&s->dma_adc.wait);
+ if (!s->dma_adc.mapped) {
if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
s->ctrl &= ~CTRL_ADC_EN;
outl(s->ctrl, s->io+ES1371_REG_CONTROL);
s->dma_adc.error++;
}
- if (s->dma_adc.count > 0)
- wake_up(&s->dma_adc.wait);
}
}
/* update DAC1 pointer */
@@ -867,7 +870,7 @@ static void es1371_update_ptr(struct es1371_state *s)
s->dma_dac1.fragsize, (s->sctrl & SCTRL_P1SEB) ? 0 : 0x80);
s->dma_dac1.endcleared = 1;
}
- if (s->dma_dac1.count < (signed)s->dma_dac1.dmasize)
+ if (s->dma_dac1.count + (signed)s->dma_dac1.fragsize <= (signed)s->dma_dac1.dmasize)
wake_up(&s->dma_dac1.wait);
}
}
@@ -890,7 +893,7 @@ static void es1371_update_ptr(struct es1371_state *s)
s->dma_dac2.fragsize, (s->sctrl & SCTRL_P2SEB) ? 0 : 0x80);
s->dma_dac2.endcleared = 1;
}
- if (s->dma_dac2.count < (signed)s->dma_dac2.dmasize)
+ if (s->dma_dac2.count + (signed)s->dma_dac2.fragsize <= (signed)s->dma_dac2.dmasize)
wake_up(&s->dma_dac2.wait);
}
}
@@ -1443,7 +1446,7 @@ static int drain_dac1(struct es1371_state *s, int nonblock)
unsigned long flags;
int count, tmo;
- if (s->dma_dac1.mapped)
+ if (s->dma_dac1.mapped || !s->dma_dac1.ready)
return 0;
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1478,7 +1481,7 @@ static int drain_dac2(struct es1371_state *s, int nonblock)
unsigned long flags;
int count, tmo;
- if (s->dma_dac2.mapped)
+ if (s->dma_dac2.mapped || !s->dma_dac2.ready)
return 0;
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&s->dma_dac2.wait, &wait);
@@ -1623,27 +1626,22 @@ static unsigned int es1371_poll(struct file *file, struct poll_table_struct *wai
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_flags & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE)
poll_wait(file, &s->dma_dac2.wait, wait);
- if (file->f_flags & FMODE_READ)
+ if (file->f_mode & FMODE_READ)
poll_wait(file, &s->dma_adc.wait, wait);
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
- if (file->f_flags & FMODE_READ) {
- if (s->dma_adc.mapped) {
+ if (file->f_mode & FMODE_READ) {
if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
mask |= POLLIN | POLLRDNORM;
- } else {
- if (s->dma_adc.count > 0)
- mask |= POLLIN | POLLRDNORM;
- }
}
- if (file->f_flags & FMODE_WRITE) {
+ if (file->f_mode & FMODE_WRITE) {
if (s->dma_dac2.mapped) {
if (s->dma_dac2.count >= (signed)s->dma_dac2.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if ((signed)s->dma_dac2.dmasize > s->dma_dac2.count)
+ if ((signed)s->dma_dac2.dmasize >= s->dma_dac2.count + (signed)s->dma_dac2.fragsize)
mask |= POLLOUT | POLLWRNORM;
}
}
@@ -2044,11 +2042,11 @@ static int es1371_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE)
drain_dac2(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
- if (file->f_flags & FMODE_WRITE) {
+ if (file->f_mode & FMODE_WRITE) {
stop_dac2(s);
dealloc_dmabuf(&s->dma_dac2);
}
- if (file->f_flags & FMODE_READ) {
+ if (file->f_mode & FMODE_READ) {
stop_adc(s);
dealloc_dmabuf(&s->dma_adc);
}
@@ -2148,7 +2146,7 @@ static unsigned int es1371_poll_dac(struct file *file, struct poll_table_struct
if (s->dma_dac1.count >= (signed)s->dma_dac1.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if ((signed)s->dma_dac1.dmasize > s->dma_dac1.count)
+ if ((signed)s->dma_dac1.dmasize >= s->dma_dac1.count + (signed)s->dma_dac1.fragsize)
mask |= POLLOUT | POLLWRNORM;
}
spin_unlock_irqrestore(&s->lock, flags);
@@ -2538,16 +2536,16 @@ static unsigned int es1371_midi_poll(struct file *file, struct poll_table_struct
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_flags & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE)
poll_wait(file, &s->midi.owait, wait);
- if (file->f_flags & FMODE_READ)
+ if (file->f_mode & FMODE_READ)
poll_wait(file, &s->midi.iwait, wait);
spin_lock_irqsave(&s->lock, flags);
- if (file->f_flags & FMODE_READ) {
+ if (file->f_mode & FMODE_READ) {
if (s->midi.icnt > 0)
mask |= POLLIN | POLLRDNORM;
}
- if (file->f_flags & FMODE_WRITE) {
+ if (file->f_mode & FMODE_WRITE) {
if (s->midi.ocnt < MIDIOUTBUF)
mask |= POLLOUT | POLLWRNORM;
}
@@ -2672,11 +2670,17 @@ static /*const*/ struct file_operations es1371_midi_fops = {
/* maximum number of devices */
#define NR_DEVICE 5
+#if CONFIG_SOUND_ES1371_JOYPORT_BOOT
+static int joystick[NR_DEVICE] = {
+CONFIG_SOUND_ES1371_GAMEPORT
+, 0, };
+#else
static int joystick[NR_DEVICE] = { 0, };
+#endif
/* --------------------------------------------------------------------- */
-static const struct initvol {
+static struct initvol {
int mixch;
int vol;
} initvol[] __initdata = {
@@ -2708,7 +2712,7 @@ __initfunc(int init_es1371(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1371: version v0.4 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1371: version v0.8 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
if (pcidev->base_address[0] == 0 ||
@@ -2736,20 +2740,20 @@ __initfunc(int init_es1371(void))
goto err_region;
}
request_region(s->io, ES1371_EXTENT, "es1371");
- if (request_irq(s->irq, es1371_interrupt, SA_INTERRUPT|SA_SHIRQ, "es1371", s)) {
+ if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
goto err_irq;
}
printk(KERN_INFO "es1371: found adapter at io %#06x irq %u\n"
KERN_INFO "es1371: features: joystick 0x%x\n", s->io, s->irq, joystick[index]);
/* register devices */
- if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops)) < 0)
+ if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
goto err_dev1;
- if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops)) < 0)
+ if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
goto err_dev2;
- if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops)) < 0)
+ if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
goto err_dev3;
- if ((s->dev_midi = register_sound_midi(&es1371_midi_fops)) < 0)
+ if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
goto err_dev4;
/* initialize codec registers */
s->ctrl = 0;
@@ -2758,7 +2762,6 @@ __initfunc(int init_es1371(void))
printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
else {
s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
- request_region(joystick[index], JOY_EXTENT, "es1371");
}
}
s->sctrl = 0;
@@ -2880,8 +2883,6 @@ void cleanup_module(void)
synchronize_irq();
free_irq(s->irq, s);
release_region(s->io, ES1371_EXTENT);
- if (s->ctrl & CTRL_JYSTK_EN)
- release_region(((((s->ctrl >> CTRL_JOY_SHIFT) & CTRL_JOY_MASK) << 3) | 0x200), JOY_EXTENT);
unregister_sound_dsp(s->dev_audio);
unregister_sound_mixer(s->dev_mixer);
unregister_sound_dsp(s->dev_dac);
diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c
index 3c46d7ada..a00ffb63a 100644
--- a/drivers/sound/gus_card.c
+++ b/drivers/sound/gus_card.c
@@ -128,17 +128,20 @@ void gusintr(int irq, void *dev_id, struct pt_regs *dummy)
{
unsigned char src;
extern int gus_timer_enabled;
- struct address_info *hw_config=dev_id;
sti();
#ifdef CONFIG_GUSMAX
- if (have_gus_max)
+ if (have_gus_max) {
+ struct address_info *hw_config = dev_id;
adintr(irq, (void *)hw_config->slots[1], NULL);
+ }
#endif
#ifdef CONFIG_GUS16
- if (db16)
+ if (db16) {
+ struct address_info *hw_config = dev_id;
adintr(irq, (void *)hw_config->slots[3], NULL);
+ }
#endif
while (1)
diff --git a/drivers/sound/gus_wave.c b/drivers/sound/gus_wave.c
index 4bf4cd38d..b0eacde38 100644
--- a/drivers/sound/gus_wave.c
+++ b/drivers/sound/gus_wave.c
@@ -144,7 +144,6 @@ static struct voice_info voices[32];
static int freq_div_table[] =
{
- 44100,
44100, /* 14 */
41160, /* 15 */
38587, /* 16 */
@@ -1173,7 +1172,6 @@ static int guswave_kill_note(int dev, int voice, int note, int velocity)
gus_voice_fade(voice);
}
- restore_flags(flags);
return 0;
}
@@ -2235,9 +2233,6 @@ static int gus_audio_open(int dev, int mode)
gus_busy = 1;
active_device = 0;
- gus_reset();
- reset_sample_memory();
- gus_select_max_voices(14);
saved_iw_mode = iw_mode;
if (iw_mode)
{
@@ -2245,6 +2240,11 @@ static int gus_audio_open(int dev, int mode)
gus_write8(0x19, gus_read8(0x19) & ~0x01); /* Disable enhanced mode */
iw_mode = 0;
}
+
+ gus_reset();
+ reset_sample_memory();
+ gus_select_max_voices(14);
+
pcm_active = 0;
dma_active = 0;
pcm_opened = 1;
@@ -2933,7 +2933,6 @@ void gus_wave_init(struct address_info *hw_config)
int gus_type = 0x24; /* 2.4 */
int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
- int dev;
int sdev;
hw_config->slots[0] = -1; /* No wave */
diff --git a/drivers/sound/legacy.h b/drivers/sound/legacy.h
index cde5bc2fc..6c3b87ce6 100644
--- a/drivers/sound/legacy.h
+++ b/drivers/sound/legacy.h
@@ -33,6 +33,7 @@
#define CONFIG_SB
#define CONFIG_SOFTOSS
#define CONFIG_SSCAPE
+#define CONFIG_AD1816
#define CONFIG_TRIX
#define CONFIG_VMIDI
#define CONFIG_YM3812
diff --git a/drivers/sound/lowlevel/ChangeLog.awe b/drivers/sound/lowlevel/ChangeLog.awe
deleted file mode 100644
index 196da64d4..000000000
--- a/drivers/sound/lowlevel/ChangeLog.awe
+++ /dev/null
@@ -1,206 +0,0 @@
-ver.0.4.2c
- - Add a mode to enable drum channel toggle via bank number
- change.
-
-ver.0.4.2b
- - Clear voice position after note on
- - Change nrvoices according to the current playing mode
-
-ver.0.4.2a
- - Fix a bug in pitch calculation with scale parameter
- - Change default chorus & reverb modes
-
-ver.0.4.2
- - Use indirect voice allocation mode; used as default mode
- - Add preset mapping
- - Free buffers when resetting samples
- - Set default preset/bank/drumset as variable
- - Fix a bug in exclusive note-off
- - Add channel reset control macro
- - Change modwheel sensitivity as variable
- - Add lock option in open_patch
- - Add channel priority mode macro, and disable it as default
- - Add unset effect macro
- - Add user defined chorus/reverb modes
- - Do not initialize effect parameters when allocating voices
- - Accept realtime filter-Q parameter change
- - Check value range of set/add effects
- - Change drum flags automatically when receiving bank #128
-
-ver.0.4.1 development versions
-
-ver.0.4.0c
- - Fix kernel oops when setting AWE_FX_ATTEN
-
-ver.0.4.0b
- - Do not kill_note in start_note when velocity is zero
-
-ver.0.4.0a
- - Fix a bug in channel pressure effects
-
-ver.0.4.0
- - Support dynamic buffer allocation
- - Add functions to open/close/unload a patch
- - Change from pointer to integer index in voice/sample lists
- - Support for Linux/Alpha-AXP
- - Fix for FreeBSD
- - Add sostenuto control
- - Add midi channel priority
- - Fix a bug in all notes off control
- - Use AWE_DEFAULT_MEMSIZE always if defined
- - Fix a bug in awe_reset causes seg fault when no DRAM onboard
- - Use awe_mem_start variable instead of constant
-
-ver.0.3.3c
- - Fix IOCTL_TO_USER for OSS-3.8 (on Linux-2.1.25)
- - Fix i/o macros for mixer controls
-
-ver.0.3.3b
- - Fix version number in awe_version.h
- - Fix a small bug in noteoff/relese all
-
-ver.0.3.3a
- - Fix all notes/sounds off
- - Add layer effect control
- - Add misc mode controls; realtime pan, version number, etc.
- - Move gus bank control in misc mode control
- - Modify awe_operations for OSS3.8b5
- - Fix installation script
-
-ver.0.3.3
- - Add bass/treble control in Emu8000 chip
- - Add mixer device
- - Fix sustain on to value 127
-
-ver.0.3.2
- - Refuse linux-2.0.0 at installation
- - Move awe_voice.h to /usr/include/linux
-
-ver.0.3.1b (not released)
- - Rewrite chorus/reverb mode change functions
- - Rewrite awe_detect & awe_check_dram routines
-
-ver.0.3.1a
- - Fix a bug to reset voice counter in awe_reset
- - Fix voice balance on GUS mode
- - Make symlink on /usr/include/asm in install script
-
-ver.0.3.1
- - Remove zero size arrays from awe_voice.h
- - Fix init_fm routine
- - Remove all samples except primary samples in REMOVE_LAST_SAMPLES
-
-ver.0.3.0a
- - Add AWE_NOTEOFF_ALL control
- - Remove AWE_INIT_ATTEN control
-
-ver.0.3.0
- - Fix decay time table
- - Add exclusive sounds mode
- - Add capability to get current status
-
-ver.0.2.99e
- - Add #ifdef for all sounds/notes off controls.
- - Fix bugs on searching the default drumset/preset.
- - Fix usslite patch to modify the default Config.in.
-
-ver.0.2.99d
- - Fix bugs of attack/hold parameters
- - Fix attack & decay time table
-
-ver.0.2.99c
- - Change volume control messages (main & expression volume)
- to accesspt normal MIDI parameters in channel mode.
- - Use channel mode in SEQ2 controls.
-
-ver.0.2.99b
- - #ifdef patch manager functions (for OSS-3.7)
-
-ver.0.2.99a
- - Fix sustain bug
-
-ver.0.2.99 (0.3 beta)
- - Support multiple instruments
-
-ver.0.2.0c
- - Add copyright notice
- - FreeBSD 2.2-ALPHA integration
-
-ver.0.2.0b
- - Remove buffered reading appended in v0.2.0a
- - Remove SMAxW register check on writing
- - Support Linux 2.1.x kernel
- - Rewrite installation script
-
-ver.0.2.0a
- - Define SEQUENCER_C for tuning.h for FreeBSD system
- - Improvement of sample loading speed
- - Fix installation script
- - Add PnP driver functions for ISA PnP driver support
-
-ver.0.2.0
- - Includes FreeBSD port
- - Can load GUS compatible patches
- - Change values of hardware control parameters for compatibility
- with GUS driver
- - Accept 8bit or unsigned wave data
- - Accept no blank loop data
- - Add sample mode flags in sample_info
-
-ver.0.1.6
- - Add voice effects control
- - Fix awe_voice.h for word alignment
-
-ver.0.1.5c
- - Fix FM(OPL) playback problem
-
-ver.0.1.5b
- - Fix pitch calculation for fixed midi key
-
-ver.0.1.5a
- - Fix bugs in removing samples from linked list.
-
-ver.0.1.5
- - Add checksum verification for sample uploading
- (not compatible from older sample_info structure)
- - Fix sample offset pointers to (actual value - 1)
- - Add sequencer command to initialize awe32
-
-ver.0.1.4c
- - Fix card detection and memory check function to avoid system crash
- at booting
-
-ver.0.1.4b
- - Add release sustain mode
- - Initialize FM each time after loading samples
-
-ver.0.1.4a
- - Fix AWE card detection code
- - Correct FM initialize position
- - Add non-releasing mode on voice info
-
-ver.0.1.4
- - Add AWE card and DRAM detection codes
- - Add FM initialization code
- - Modify volume control
- - Remove linear volume mode
- - Change memory management; not using malloc dynamically
- - Add remove-samples command
- - Use internal id implicitly at loading samples
-
-ver.0.1.3
- - Fix a bug on patch uploading to RAM
-
-ver.0.1.2
- - Divide to separated packages
- - Fix disagreed macro conditions
- - Fix unresolved function bugs
- - Integrate VoxWare and USS-Lite driver source (awe_voice.c)
- and remove awe_card.c
-
-ver.0.1.1
- - Fix wrong sample numbers in sbktext
- - Fix txt2sfx bug
- - Fix pan parameter calculation
- - Append USS-Lite/Linux2.0 driver
-
diff --git a/drivers/sound/lowlevel/Config.in b/drivers/sound/lowlevel/Config.in
index 36928af08..09a9f7249 100644
--- a/drivers/sound/lowlevel/Config.in
+++ b/drivers/sound/lowlevel/Config.in
@@ -6,6 +6,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND" = "m" ]; then
dep_tristate 'Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_AEDSP16 $CONFIG_SOUND_OSS
if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
hex ' I/O base for Audio Excel DSP 16 220 or 240' CONFIG_AEDSP16_BASE 220
+ hex 'I/O base for MPU401 Check from manual of the card' CONFIG_MPU_BASE 330
fi
if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
@@ -23,9 +24,9 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND" = "m" ]; then
bool 'Audio Excel DSP 16 (SBPro emulation)' CONFIG_AEDSP16_SBPRO
if [ "$CONFIG_AEDSP16_SBPRO" = "y" ]; then
comment 'Audio Excel DSP 16 [Sound Blaster Pro]'
- hex 'I/O base for Audio Excel DSP 16 220, 240' CONFIG_AEDSP16_BASE $CONFIG_SB_BASE
- int 'Audio Excel DSP 16 IRQ 5, 7, 9, 10, 11' CONFIG_AEDSP16_SB_IRQ $CONFIG_SB_IRQ
- int 'Audio Excel DSP 16 DMA 0, 1 or 3' CONFIG_AEDSP16_SB_DMA $CONFIG_SB_DMA
+ hex 'I/O base for Audio Excel DSP 16 220, 240' CONFIG_AEDSP16_BASE $CONFIG_SB_BASE 220
+ int 'Audio Excel DSP 16 IRQ 5, 7, 9, 10, 11' CONFIG_AEDSP16_SB_IRQ $CONFIG_SB_IRQ 5
+ int 'Audio Excel DSP 16 DMA 0, 1 or 3' CONFIG_AEDSP16_SB_DMA $CONFIG_SB_DMA 0
fi
fi
fi
@@ -36,8 +37,8 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND" = "m" ]; then
if [ "$CONFIG_AEDSP16_MSS" = "y" ]; then
comment 'Audio Excel DSP 16 [Microsoft Sound System]'
hex 'I/O base for Audio Excel DSP 16 220 or 240' CONFIG_AEDSP16_BASE 220
- int 'Audio Excel DSP 16 IRQ 5, 7, 9, 10, 11' CONFIG_AEDSP16_MSS_IRQ $CONFIG_MSS_IRQ
- int 'Audio Excel DSP 16 DMA 0, 1 or 3' CONFIG_AEDSP16_MSS_DMA $CONFIG_MSS_DMA
+ int 'Audio Excel DSP 16 IRQ 5, 7, 9, 10, 11' CONFIG_AEDSP16_MSS_IRQ $CONFIG_MSS_IRQ 5
+ int 'Audio Excel DSP 16 DMA 0, 1 or 3' CONFIG_AEDSP16_MSS_DMA $CONFIG_MSS_DMA 1
fi
fi
fi
diff --git a/drivers/sound/lowlevel/README b/drivers/sound/lowlevel/README
index 76fba8dee..da66e3396 100644
--- a/drivers/sound/lowlevel/README
+++ b/drivers/sound/lowlevel/README
@@ -1,12 +1,11 @@
Additional low level sound drivers for Linux
============================================
-This directory contains additional low level sound drivers which
-are not part of USS/Lite (Open Sound System). These drivers are
-maintained by their authors (not by Hannu Savolainen).
-
-If you like to write a new low level sound driver, please contact
-Hannu Savolainen (hannu@voxware.pp.fi) for more info.
+This directory contains some low level sound drivers.
+These drivers are used to be (when Linux sound drivers was OSS/Lite) external
+drivers, not maintained by Hannu Savolainen and not touched by him.
+Now things are changed: the new Linux sound driver code maintained by Alan Cox
+include these lowlevel drivers and they are no more neglected (thanks Alan).
The following low level drivers are included:
@@ -15,4 +14,9 @@ The following low level drivers are included:
- Audio Excel DSP 16 initialization driver by Riccardo Facchetti
(fizban@tin.it)
- SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai
- (iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more info.
+ (iwai@dragon.mm.t.u-tokyo.ac.jp).
+
+You can find documentation for these drivers in the Documentation/sound
+directory.
+
+[ File edited 17.01.1999 - Riccardo Facchetti ]
diff --git a/drivers/sound/lowlevel/README.awe b/drivers/sound/lowlevel/README.awe
deleted file mode 100644
index 1765d4b15..000000000
--- a/drivers/sound/lowlevel/README.awe
+++ /dev/null
@@ -1,205 +0,0 @@
-================================================================
- AWE32 Sound Driver for Linux and FreeBSD
- version 0.4.2c; Oct. 7, 1997
-================================================================
-
-* GENERAL NOTES
-
-This is a sound driver extension for the Sound Blaster AWE32 and other
-compatible cards (AWE32-PnP, SB32, SB32-PnP, AWE64, etc.) to enable
-the wave synth operations. The driver is provided for both Linux
-1.2.x and 2.[01].x kernels, and also FreeBSD on Intel x86 and DEC
-Alpha systems. See INSTALL.awe (or INSTALL.fbsd) document for
-installation of the driver package.
-
-This driver was written by Takashi Iwai (iwai@dragon.mm.t.u-tokyo.ac.jp)
-who also maintains the code. Please forward any questions, bug fixes
-and suggestions directly to Iwai (_NOT_ to Linus Torvalds or Hannu
-Savolainen).
-
-
-* NOTE TO LINUX USERS
-
-To enable this driver on linux-2.[01].x kernels, you need turn on both
-"lowlevel drivers support" and "AWE32 synth support" options in sound
-menu when configure your linux kernel and modules. For more details,
-see the installation document in the original driver package
-(awedrv-0.4.2.tar.gz) available at the web page:
- http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
-
-If you're using PnP cards, the card must be initialized before loading
-the sound driver. There're several options to do this:
- - Initialize the card via ISA PnP tools, and load the sound module.
- - Initialize the card on DOS, and load linux by loadlin.exe
- - Use PnP driver (for Linux-2.x.x)
-See the FAQ list on the URL above.
-
-
-* USING THE DRIVER
-
-The GM and GS sounds include multiple instrument layers.
-The current version supports this type of sounds with a special
-extension, but it uses a non-standard way of sequencer calls. Then,
-so far, only drvmidi and playmidi can play the multiple instruments
-and stereo sounds properly as MIDI sequencers.
-
-To load SoundFont files, sfxload utility is required.
-All AWE32 driver and utilities can be downloaded from:
- http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
-
-The sfxload is included in the package awesfx-0.4.2.tgz. Binary
-packages are available there, too. See the instruction in each
-package for installation.
-
-Sfxload reads a SoundFont file and transfers it to the sound driver.
-Note that new sfxload no longer requires -i option.
-
- % sfxload synthgm.sbk
-
-You can tune up the sound via some new options, -A, -a and -d.
-
- % sfxload -A2 synthgm.sbk
-
-See the manual of sfxload for more details.
-
-Now you can hear midi musics by supported midi players (drvmidi or
-playmidi-2.5).
-
- % drvmidi foo.mid
-
-If you have only 512kb on the sound card, I recommend to use dynamic
-sample loading via -L option of drvmidi. 2MB GM/GS soundfont file is
-available in most midi files.
-
- % sfxload synthgm
- % drvmidi -L 2mbgmgs foo.mid
-
-Enjoy.
-
-
-* COMPILE FLAGS
-
-Compile conditions are defined in awe_config.h.
-
-[Compatibility Conditions]
-The following flags are defined automatically when using installation
-shell script.
-
-- AWE_OBSOLETE_VOXWARE (default: not defined)
- indicates the system is VoxWare-3.0.x (with linux 1.2.x or
- FreeBSD) if defined.
-
-- AWE_NEW_KERNEL_INTERFACE (default: not defined)
- indicates the system is OSSLite on Linux 2.1.6 or later if
- defined.
-
-- HAS_LOWLEVEL_H (default: not defined)
- indicates the system has "lowlevel.h" in the sound/lowlevel
- directory. OSS driver has this file.
-
-- AWE_NO_PATCHMGR (default: not defined)
- indicates the sound driver has no patch manager function (for
- OSS-3.707 (in Linux-2.1.13) or newer).
-
-- AWE_OSS38 (default: not defined)
- indicates the sound driver has an additional parameter in
- operation table (for OSS-3.8b5 in Linux-2.1.25 or newer).
-
-
-[Hardware Conditions]
-You don't have to define the following two values.
-Define them only when the driver couldn't detect the card properly.
-
-- AWE_DEFAULT_BASE_ADDR (default: not defined)
- specifies the base port address of your AWE32 card.
-
-- AWE_DEFAULT_MEM_SIZE (default: not defined)
- specifies the memory size of your AWE32 card in kilo bytes.
-
-
-[Sample Table Size]
-From ver.0.4.0, sample tables are allocated dynamically (except
-Linux-1.2.x system), so you need NOT to touch these parameters.
-Linux-1.2.x users may need to increase these values for sound
-cards equipped with more DRAM.
-
-- AWE_MAX_SF_LISTS, AWE_MAX_SAMPLES, AWE_MAX_INFOS
-
-
-[Other Conditions]
-
-- AWE_ALWAYS_INIT_FM (default: not defined)
- indicates the AWE driver always initialize FM passthrough even
- without DRAM on board. Emu8000 chip has a restriction for playing
- samples on DRAM that at least two channels must be occupied as
- passthrough channels.
-
-- AWE_DEBUG_ON (default: defined)
- turns on debugging messages if defined.
-
-- AWE_HAS_GUS_COMPATIBILITY (default: defined)
- Enables GUS compatibility mode if defined, reading GUS patches and
- GUS control commands. Define this option to use GMOD or other
- GUS module players.
-
-- AWE_ACCEPT_ALL_SOUNDS_CONTROL (default: defined)
- Enables MIDI control #120 and #123 as "all notes off" and "all
- sounds off" events, respectively.
-
-- CONFIG_AWE32_MIXER (default: defined)
- Adds a mixer device for AWE32 bass/treble equalizer control.
- You can access this device using /dev/mixer?? (usually mixer01).
-
-- AWE_LOOKUP_MIDI_PRIORIITY (default: defined)
- Allocates voices according to MIDI channel priority.
- Drum channels have the highest priorit, followed by #1, #2, and
- so on.
-
-- DEF_FM_CHORUS_DEPTH (default: 0x10)
- The default strength to be sent to the chorus effect engine.
- From 0 to 0xff. Larger numbers may often cause weird sounds.
-
-- DEF_FM_REVERB_DEPTH (default: 0x10)
- The default strength to be sent to the reverb effect engine.
- From 0 to 0xff. Larger numbers may often cause weird sounds.
-
-
-* ACKNOWLEDGMENTS
-
-Thanks to Witold Jachimczyk (witek@xfactor.wpi.edu) for much advice
-on programming of AWE32. Much code is brought from his AWE32-native
-MOD player, ALMP.
-The port of awedrv to FreeBSD was done by Randall Hopper
-(rhh@ct.picker.com).
-I also thank linux-awe-ml members for their efforts
-to reboot their systems many times. :-)
-
-
-* BUGS & TODO'S
-
-- can't detect DRAM size on some cards
-- smarter patch management
-- smarter DRAM memory control
-- etc., etc., etc.
-
-
-* COPYRIGHT
-
-Copyright (C) 1996, 1997 Takashi Iwai
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the 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.
-
-
-Takashi Iwai <iwai@dragon.mm.t.u-tokyo.ac.jp>
diff --git a/drivers/sound/lowlevel/awe_compat-fbsd.h b/drivers/sound/lowlevel/awe_compat-fbsd.h
new file mode 100644
index 000000000..cbb01dc5c
--- /dev/null
+++ b/drivers/sound/lowlevel/awe_compat-fbsd.h
@@ -0,0 +1,173 @@
+/*
+ * sound/awe_compat.h
+ *
+ * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
+ * version 0.4.3; Nov. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_COMPAT_H_DEF
+#define AWE_COMPAT_H_DEF
+
+/*================================================================
+ * version check
+ *================================================================*/
+
+/* FreeBSD version check */
+#include <i386/isa/sound/awe_config.h>
+
+#define AWE_OBSOLETE_VOXWARE
+#if __FreeBSD__ >= 2
+# include <osreldate.h>
+# if __FreeBSD_version >= 300000
+# undef AWE_OBSOLETE_VOXWARE
+# endif
+#endif
+#ifdef __linux__
+# include <linux/config.h>
+#endif
+
+
+/*================================================================
+ * INCLUDE OTHER HEADER FILES
+ *================================================================*/
+
+/* reading configuration of sound driver */
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include <i386/isa/sound/sound_config.h>
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#ifdef HAS_LOWLEVEL_H
+#include "lowlevel.h"
+#endif
+
+#include <i386/isa/sound/sound_config.h>
+#if defined(CONFIGURE_SOUNDCARD) && defined(CONFIG_AWE32)
+# define CONFIG_AWE32_SYNTH
+#endif
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * include AWE header files
+ *================================================================*/
+
+#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
+
+#include <i386/isa/sound/awe_hw.h>
+#include <i386/isa/sound/awe_version.h>
+#include <i386/isa/sound/awe_voice.h>
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* include finetune table */
+#ifdef AWE_OBSOLETE_VOXWARE
+# define SEQUENCER_C
+#endif
+#include <i386/isa/sound/tuning.h>
+#include <machine/ultrasound.h>
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
+/*----------------------------------------------------------------
+ * compatibility macros for AWE32 driver
+ *----------------------------------------------------------------*/
+
+/* redefine following macros */
+#undef IOCTL_IN
+#undef IOCTL_OUT
+#undef OUTW
+#undef COPY_FROM_USER
+#undef COPY_TO_USER
+#undef GET_BYTE_FROM_USER
+#undef GET_SHORT_FROM_USER
+#undef IOCTL_TO_USER
+
+/* inline is not checked yet.. maybe it'll work */
+#define INLINE /*inline*/
+
+#define KERN_WARNING /**/
+
+/*----------------------------------------------------------------
+ * memory management for freebsd
+ *----------------------------------------------------------------*/
+
+/* i/o requests; nothing */
+#define awe_check_port() 0 /* always false */
+#define awe_request_region() /* nothing */
+#define awe_release_region() /* nothing */
+
+#define AWE_DYNAMIC_BUFFER
+
+#define my_malloc_init(ptr) /* nothing */
+#define my_malloc_memptr() 0
+#define my_malloc(size) malloc(size, M_TEMP, M_WAITOK)
+#define my_free(ptr) if (ptr) {free(ptr, M_TEMP);}
+
+#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
+
+/*----------------------------------------------------------------
+ * i/o interfaces for freebsd
+ *----------------------------------------------------------------*/
+
+/* according to linux rule; the arguments are swapped */
+#define OUTW(data,addr) outw(addr, data)
+
+#define COPY_FROM_USER(target,source,offs,count) \
+ uiomove(((caddr_t)(target)),(count),((struct uio *)(source)))
+#define COPY_TO_USER(target,source,offs,count) \
+ uiomove(((caddr_t)(source)),(count),((struct uio *)(target)))
+#define GET_BYTE_FROM_USER(target,addr,offs) \
+ uiomove(((char*)&(target)), 1, ((struct uio *)(addr)))
+#define GET_SHORT_FROM_USER(target,addr,offs) \
+ uiomove(((char*)&(target)), 2, ((struct uio *)(addr)))
+#define IOCTL_TO_USER(target,offs,source,count) \
+ memcpy(&((target)[offs]), (source), (count))
+#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN)
+#define IOCTL_IN(arg) (*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+#define BZERO(target,len) bzero((caddr_t)target, len)
+#define MEMCPY(dst,src,len) bcopy((caddr_t)src, (caddr_t)dst, len)
+
+#ifndef AWE_OBSOLETE_VOXWARE
+# define printk printf
+# define RET_ERROR(err) -err
+#endif
+
+
+/* old style device tables (not modulized) */
+#define sound_alloc_synthdev() \
+ (num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
+#define sound_alloc_mixerdev() \
+ (num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
+#define sound_alloc_mididev() \
+ (num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
+#define sound_unload_synthdev(dev) /**/
+#define sound_unload_mixerdev(dev) /**/
+#define sound_unload_mididev(dev) /**/
+
+
+#endif /* CONFIG_AWE32_SYNTH */
+
+#endif /* AWE_COMPAT_H_DEF */
diff --git a/drivers/sound/lowlevel/awe_compat-linux.h b/drivers/sound/lowlevel/awe_compat-linux.h
new file mode 100644
index 000000000..6ab482ac4
--- /dev/null
+++ b/drivers/sound/lowlevel/awe_compat-linux.h
@@ -0,0 +1,248 @@
+/*
+ * sound/awe_compat.h
+ *
+ * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
+ * version 0.4.3; Oct. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_COMPAT_H_DEF
+#define AWE_COMPAT_H_DEF
+
+/*================================================================
+ * version check
+ *================================================================*/
+
+#include "awe_config.h"
+
+#define ASC_LINUX_VERSION(V,P,S) (((V) * 65536) + ((P) * 256) + (S))
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+/* linux version check */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+#define AWE_OBSOLETE_VOXWARE
+#endif
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
+#define AWE_NEW_KERNEL_INTERFACE
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,80)
+#define AWE_MODULE_SUPPORT
+#endif
+#endif
+
+#ifdef AWE_OBSOLETE_VOXWARE
+#include "soundvers.h"
+#else
+#include "../soundvers.h"
+#endif
+
+#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
+/* OSS/Free-3.8 */
+#define AWE_NO_PATCHMGR
+#define AWE_OSS38
+#define HAS_LOWLEVEL_H
+#endif
+
+/*================================================================
+ * INCLUDE OTHER HEADER FILES
+ *================================================================*/
+
+/* set up module */
+
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include "../soundmodule.h"
+#endif
+
+
+/* reading configuration of sound driver */
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include "sound_config.h"
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#ifdef HAS_LOWLEVEL_H
+#include "lowlevel.h"
+#endif
+
+#include "../sound_config.h"
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * include AWE header files
+ *================================================================*/
+
+#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
+
+#include "awe_hw.h"
+#include "awe_version.h"
+#include <linux/awe_voice.h>
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* include finetune table */
+#ifdef AWE_OBSOLETE_VOXWARE
+# include "tuning.h"
+#else
+# include "../tuning.h"
+#endif
+#include <linux/ultrasound.h>
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
+/*----------------------------------------------------------------
+ * compatibility macros for AWE32 driver
+ *----------------------------------------------------------------*/
+
+/* redefine following macros */
+#undef IOCTL_IN
+#undef IOCTL_OUT
+#undef OUTW
+#undef COPY_FROM_USER
+#undef COPY_TO_USER
+#undef GET_BYTE_FROM_USER
+#undef GET_SHORT_FROM_USER
+#undef IOCTL_TO_USER
+
+/* use inline prefix */
+#define INLINE inline
+
+/*----------------------------------------------------------------
+ * memory management for linux
+ *----------------------------------------------------------------*/
+
+#ifdef AWE_OBSOLETE_VOXWARE
+/* old type linux system */
+
+/* i/o requests; nothing */
+#define awe_check_port() 0 /* always false */
+#define awe_request_region() /* nothing */
+#define awe_release_region() /* nothing */
+
+static int _mem_start; /* memory pointer for permanent buffers */
+
+#define my_malloc_init(memptr) _mem_start = (memptr)
+#define my_malloc_memptr() _mem_start
+#define my_free(ptr) /* do nothing */
+
+/* allocate buffer only once */
+#define INIT_TABLE(buffer,index,nums,type) {\
+PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
+}
+
+#else
+
+#define AWE_DYNAMIC_BUFFER
+
+#define my_malloc_init(ptr) /* nothing */
+#define my_malloc_memptr() 0
+#define my_malloc(size) vmalloc(size)
+#define my_free(ptr) if (ptr) {vfree(ptr);}
+
+/* do not allocate buffer at beginning */
+#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
+
+/* old type macro */
+#define RET_ERROR(err) -err
+
+#endif
+
+/*----------------------------------------------------------------
+ * i/o interfaces for linux
+ *----------------------------------------------------------------*/
+
+#define OUTW(data,addr) outw(data, addr)
+
+#ifdef AWE_NEW_KERNEL_INTERFACE
+#define COPY_FROM_USER(target,source,offs,count) \
+ copy_from_user(target, (source)+(offs), count)
+#define GET_BYTE_FROM_USER(target,addr,offs) \
+ get_user(target, (unsigned char*)&((addr)[offs]))
+#define GET_SHORT_FROM_USER(target,addr,offs) \
+ get_user(target, (unsigned short*)&((addr)[offs]))
+#ifdef AWE_OSS38
+#define IOCTL_TO_USER(target,offs,source,count) \
+ memcpy(target, (source)+(offs), count)
+#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE)
+#else
+#define IOCTL_TO_USER(target,offs,source,count) \
+ copy_to_user(target, (source)+(offs), count)
+#define IO_WRITE_CHECK(cmd) (_IOC_DIR(cmd) & _IOC_WRITE)
+#endif /* AWE_OSS38 */
+#define COPY_TO_USER IOCTL_TO_USER
+#define IOCTL_IN(arg) (*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+
+#else /* old type i/o */
+#define COPY_FROM_USER(target,source,offs,count) \
+ memcpy_fromfs(target, (source)+(offs), (count))
+#define GET_BYTE_FROM_USER(target,addr,offs) \
+ *((char *)&(target)) = get_fs_byte((addr)+(offs))
+#define GET_SHORT_FROM_USER(target,addr,offs) \
+ *((short *)&(target)) = get_fs_word((addr)+(offs))
+#ifdef AWE_OSS38
+#define IOCTL_TO_USER(target,offs,source,count) \
+ memcpy(target, (source)+(offs), count)
+#define COPY_TO_USER(target,offs,source,count) \
+ memcpy_tofs(target, (source)+(offs), (count))
+#define IOCTL_IN(arg) (*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE)
+#else /* AWE_OSS38 */
+#define IOCTL_TO_USER(target,offs,source,count) \
+ memcpy_tofs(target, (source)+(offs), (count))
+#define COPY_TO_USER IOCTL_TO_USER
+#define IOCTL_IN(arg) get_fs_long((long *)(arg))
+#define IOCTL_OUT(arg,ret) snd_ioctl_return((int *)arg, ret)
+#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN)
+#endif /* AWE_OSS38 */
+
+#endif /* AWE_NEW_KERNEL_INTERFACE */
+
+#define BZERO(target,len) memset(target, 0, len)
+#define MEMCPY(dst,src,len) memcpy(dst, src, len)
+
+/* old style device tables (not modulized) */
+#ifndef AWE_MODULE_SUPPORT
+
+#define sound_alloc_synthdev() \
+ (num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
+#define sound_alloc_mixerdev() \
+ (num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
+#define sound_alloc_mididev() \
+ (num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
+#define sound_unload_synthdev(dev) /**/
+#define sound_unload_mixerdev(dev) /**/
+#define sound_unload_mididev(dev) /**/
+
+#endif /* AWE_MODULE_SUPPORT */
+
+#endif /* CONFIG_AWE32_SYNTH */
+
+#endif /* AWE_COMPAT_H_DEF */
diff --git a/drivers/sound/lowlevel/awe_compat.h b/drivers/sound/lowlevel/awe_compat.h
index 0107bd2c1..0ad4fb062 100644
--- a/drivers/sound/lowlevel/awe_compat.h
+++ b/drivers/sound/lowlevel/awe_compat.h
@@ -1,3 +1,121 @@
+/*
+ * sound/awe_compat.h
+ *
+ * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
+ * version 0.4.3; Oct. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_COMPAT_H_DEF
+#define AWE_COMPAT_H_DEF
+
+/*================================================================
+ * version check
+ *================================================================*/
+
+#include "awe_config.h"
+
+#define ASC_LINUX_VERSION(V,P,S) (((V) * 65536) + ((P) * 256) + (S))
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+/* linux version check */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+#define AWE_OBSOLETE_VOXWARE
+#endif
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
+#define AWE_NEW_KERNEL_INTERFACE
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,80)
+#define AWE_MODULE_SUPPORT
+#endif
+#endif
+
+#ifdef AWE_OBSOLETE_VOXWARE
+#include "soundvers.h"
+#else
+#include "../soundvers.h"
+#endif
+
+#if SOUND_INTERNAL_VERSION >= 0x30803
+/* OSS/Free-3.8 */
+#define AWE_NO_PATCHMGR
+#define AWE_OSS38
+#define HAS_LOWLEVEL_H
+#endif
+
+/*================================================================
+ * INCLUDE OTHER HEADER FILES
+ *================================================================*/
+
+/* set up module */
+
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include "../soundmodule.h"
+#endif
+
+
+/* reading configuration of sound driver */
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include "sound_config.h"
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#ifdef HAS_LOWLEVEL_H
+#include "lowlevel.h"
+#endif
+
+#include "../sound_config.h"
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * include AWE header files
+ *================================================================*/
+
+#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
+
+#include "awe_hw.h"
+#include "awe_version.h"
+#include <linux/awe_voice.h>
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* include finetune table */
+#ifdef AWE_OBSOLETE_VOXWARE
+# include "tuning.h"
+#else
+# include "../tuning.h"
+#endif
+#include <linux/ultrasound.h>
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
/*----------------------------------------------------------------
* compatibility macros for AWE32 driver
*----------------------------------------------------------------*/
@@ -12,14 +130,8 @@
#undef GET_SHORT_FROM_USER
#undef IOCTL_TO_USER
-#ifdef linux
-
-/*================================================================
- * Linux macros
- *================================================================*/
-
/* use inline prefix */
-#define INLINE inline
+#define INLINE /*inline*/
/*----------------------------------------------------------------
* memory management for linux
@@ -38,7 +150,6 @@ static int _mem_start; /* memory pointer for permanent buffers */
#define my_malloc_init(memptr) _mem_start = (memptr)
#define my_malloc_memptr() _mem_start
#define my_free(ptr) /* do nothing */
-#define my_realloc(buf,oldsize,size) NULL /* no realloc */
static void *my_malloc(int size)
{
@@ -46,6 +157,8 @@ static void *my_malloc(int size)
PERMANENT_MALLOC(ptr, char*, size, _mem_start);
return (void*)ptr;
}
+#define my_kmalloc(size) my_malloc(size)
+#define kfree(ptr) /* do nothing */
/* allocate buffer only once */
#define INIT_TABLE(buffer,index,nums,type) {\
@@ -60,16 +173,8 @@ buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
#define my_malloc_memptr() 0
#define my_malloc(size) vmalloc(size)
#define my_free(ptr) if (ptr) {vfree(ptr);}
-
-static void *my_realloc(void *buf, int oldsize, int size)
-{
- void *ptr;
- if ((ptr = vmalloc(size)) == NULL)
- return NULL;
- memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) );
- vfree(buf);
- return ptr;
-}
+#define my_kmalloc(size) kmalloc(size,GFP_KERNEL)
+#define my_kfree(ptr) kfree(ptr)
/* do not allocate buffer at beginning */
#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
@@ -92,7 +197,7 @@ static void *my_realloc(void *buf, int oldsize, int size)
get_user(target, (unsigned char*)&((addr)[offs]))
#define GET_SHORT_FROM_USER(target,addr,offs) \
get_user(target, (unsigned short*)&((addr)[offs]))
-#ifdef AWE_OSS38_AND_IM_A_BANANA
+#ifdef AWE_OSS38
#define IOCTL_TO_USER(target,offs,source,count) \
memcpy(target, (source)+(offs), count)
#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE)
@@ -112,79 +217,44 @@ static void *my_realloc(void *buf, int oldsize, int size)
*((char *)&(target)) = get_fs_byte((addr)+(offs))
#define GET_SHORT_FROM_USER(target,addr,offs) \
*((short *)&(target)) = get_fs_word((addr)+(offs))
+#ifdef AWE_OSS38
+#define IOCTL_TO_USER(target,offs,source,count) \
+ memcpy(target, (source)+(offs), count)
+#define COPY_TO_USER(target,offs,source,count) \
+ memcpy_tofs(target, (source)+(offs), (count))
+#define IOCTL_IN(arg) (*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+#define IO_WRITE_CHECK(cmd) (_SIOC_DIR(cmd) & _IOC_WRITE)
+#else /* AWE_OSS38 */
#define IOCTL_TO_USER(target,offs,source,count) \
memcpy_tofs(target, (source)+(offs), (count))
#define COPY_TO_USER IOCTL_TO_USER
-#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN)
#define IOCTL_IN(arg) get_fs_long((long *)(arg))
#define IOCTL_OUT(arg,ret) snd_ioctl_return((int *)arg, ret)
+#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN)
+#endif /* AWE_OSS38 */
#endif /* AWE_NEW_KERNEL_INTERFACE */
#define BZERO(target,len) memset(target, 0, len)
#define MEMCPY(dst,src,len) memcpy(dst, src, len)
+#define MEMCMP(p1,p2,len) memcmp(p1, p2, len)
+/* old style device tables (not modulized) */
+#ifndef AWE_MODULE_SUPPORT
-#elif defined(__FreeBSD__)
-
-/*================================================================
- * FreeBSD macros
- *================================================================*/
-
-/* inline is not checked yet.. maybe it'll work */
-#define INLINE /*inline*/
-
-/*----------------------------------------------------------------
- * memory management for freebsd
- *----------------------------------------------------------------*/
-
-/* i/o requests; nothing */
-#define awe_check_port() 0 /* always false */
-#define awe_request_region() /* nothing */
-#define awe_release_region() /* nothing */
-
-#define AWE_DYNAMIC_BUFFER
-
-#define my_malloc_init(ptr) /* nothing */
-#define my_malloc_memptr() 0
-#define my_malloc(size) malloc(size, M_TEMP, M_WAITOK)
-#define my_free(ptr) if (ptr) {free(ptr, M_TEMP);}
-
-#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
-
-/* it should be realloc? */
-static void *my_realloc(void *buf, int oldsize, int size)
-{
- void *ptr;
- if ((ptr = my_malloc(size)) == NULL)
- return NULL;
- memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) );
- my_free(buf);
- return ptr;
-}
-
-/*----------------------------------------------------------------
- * i/o interfaces for freebsd
- *----------------------------------------------------------------*/
-
-/* according to linux rule; the arguments are swapped */
-#define OUTW(data,addr) outw(addr, data)
+#define sound_alloc_synthdev() \
+ (num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
+#define sound_alloc_mixerdev() \
+ (num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
+#define sound_alloc_mididev() \
+ (num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
+#define sound_unload_synthdev(dev) /**/
+#define sound_unload_mixerdev(dev) /**/
+#define sound_unload_mididev(dev) /**/
-#define COPY_FROM_USER(target,source,offs,count) \
- uiomove(((caddr_t)(target)),(count),((struct uio *)(source)))
-#define COPY_TO_USER(target,source,offs,count) \
- uiomove(((caddr_t)(source)),(count),((struct uio *)(target)))
-#define GET_BYTE_FROM_USER(target,addr,offs) \
- uiomove(((char*)&(target)), 1, ((struct uio *)(addr)))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
- uiomove(((char*)&(target)), 2, ((struct uio *)(addr)))
-#define IOCTL_TO_USER(target,offs,source,count) \
- memcpy(&((target)[offs]), (source), (count))
-#define IO_WRITE_CHECK(cmd) (cmd & IOC_IN)
-#define IOCTL_IN(arg) (*(int*)(arg))
-#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
-#define BZERO(target,len) bzero((caddr_t)target, len)
-#define MEMCPY(dst,src,len) bcopy((caddr_t)src, (caddr_t)dst, len)
+#endif /* AWE_MODULE_SUPPORT */
-#endif
+#endif /* CONFIG_AWE32_SYNTH */
+#endif /* AWE_COMPAT_H_DEF */
diff --git a/drivers/sound/lowlevel/awe_config.h b/drivers/sound/lowlevel/awe_config.h
index c6b0dae6d..ffb958d49 100644
--- a/drivers/sound/lowlevel/awe_config.h
+++ b/drivers/sound/lowlevel/awe_config.h
@@ -1,10 +1,10 @@
/*
* sound/awe_config.h
*
- * Configuration of AWE32 sound driver
- * version 0.4.2; Sep. 15, 1997
+ * Configuration of AWE32/SB32/AWE64 wave table synth driver.
+ * version 0.4.3; Mar. 1, 1998
*
- * Copyright (C) 1996 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,60 +28,12 @@
* system configuration
*----------------------------------------------------------------*/
-/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD),
- * define the following line.
+/* if your kernel support module for each soundcard, define this.
+ * NOTE: it will be automatically set on linux-2.1.x kernels.
+ * only define here if you have moduler sound system on
+ * 2.0.x kernel (like RedHat).
*/
-#undef AWE_OBSOLETE_VOXWARE
-
-#ifdef __FreeBSD__
-# define AWE_OBSOLETE_VOXWARE
-#endif
-
-/* if you're using OSS-Lite on Linux 2.1.6 or later, define the
- * following line.
- */
-#define AWE_NEW_KERNEL_INTERFACE
-
-/* if you have lowlevel.h in the lowlevel directory (OSS-Lite), define
- * the following line.
- */
-#define HAS_LOWLEVEL_H
-
-/* if your system doesn't support patch manager (OSS 3.7 or newer),
- * define the following line.
- */
-#define AWE_NO_PATCHMGR
-
-/* if your system has an additional parameter (OSS 3.8b5 or newer),
- * define this.
- */
-#define AWE_OSS38
-
-/*----------------------------------------------------------------
- * AWE32 card configuration:
- * uncomment the following lines only when auto detection doesn't
- * work properly on your machine.
- *----------------------------------------------------------------*/
-
-/*#define AWE_DEFAULT_BASE_ADDR 0x620*/ /* base port address */
-/*#define AWE_DEFAULT_MEM_SIZE 512*/ /* kbytes */
-
-
-/*----------------------------------------------------------------
- * maximum size of soundfont list table:
- * you usually don't need to touch this value.
- *----------------------------------------------------------------*/
-
-#define AWE_MAX_SF_LISTS 16
-
-
-/*----------------------------------------------------------------
- * chunk size of sample and voice tables:
- * you usually don't need to touch these values.
- *----------------------------------------------------------------*/
-
-#define AWE_MAX_SAMPLES 400
-#define AWE_MAX_INFOS 800
+#undef AWE_MODULE_SUPPORT
/*----------------------------------------------------------------
@@ -106,40 +58,45 @@
/* GUS compatible mode */
#define AWE_HAS_GUS_COMPATIBILITY
-/* accept all notes/sounds off controls */
-#define AWE_ACCEPT_ALL_SOUNDS_CONTROL
+/* add MIDI emulation by wavetable */
+#define CONFIG_AWE32_MIDIEMU
/* add mixer control of emu8000 equalizer */
-#define CONFIG_AWE32_MIXER
-
-/* look up voices according to MIDI channel priority */
-#define AWE_LOOKUP_MIDI_PRIORITY
+#undef CONFIG_AWE32_MIXER
-/*----------------------------------------------------------------*/
+/* use new volume calculation method as default */
+#define AWE_USE_NEW_VOLUME_CALC
-/* reading configuration of sound driver */
+/* check current volume target for searching empty voices */
+#define AWE_CHECK_VTARGET
-#ifdef AWE_OBSOLETE_VOXWARE
+/* allow sample sharing */
+#define AWE_ALLOW_SAMPLE_SHARING
-#ifdef __FreeBSD__
-# include <i386/isa/sound/sound_config.h>
-#else
-# include "sound_config.h"
-#endif
+/*================================================================
+ * Usually, you don't have to touch the following options.
+ *================================================================*/
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
-#define CONFIG_AWE32_SYNTH
-#endif
+/*----------------------------------------------------------------
+ * AWE32 card configuration:
+ * uncomment the following lines *ONLY* when auto detection doesn't
+ * work properly on your machine.
+ *----------------------------------------------------------------*/
-#else /* AWE_OBSOLETE_VOXWARE */
+/*#define AWE_DEFAULT_BASE_ADDR 0x620*/ /* base port address */
+/*#define AWE_DEFAULT_MEM_SIZE 512*/ /* kbytes */
-#ifdef HAS_LOWLEVEL_H
-#include "lowlevel.h"
-#endif
+/*----------------------------------------------------------------
+ * maximum size of soundfont list table
+ *----------------------------------------------------------------*/
-#include "../sound_config.h"
+#define AWE_MAX_SF_LISTS 16
-#endif /* AWE_OBSOLETE_VOXWARE */
+/*----------------------------------------------------------------
+ * chunk size of sample and voice tables
+ *----------------------------------------------------------------*/
+#define AWE_MAX_SAMPLES 400
+#define AWE_MAX_INFOS 800
#endif /* AWE_CONFIG_H_DEF */
diff --git a/drivers/sound/lowlevel/awe_hw.h b/drivers/sound/lowlevel/awe_hw.h
index 7d0d88e77..c7dde2679 100644
--- a/drivers/sound/lowlevel/awe_hw.h
+++ b/drivers/sound/lowlevel/awe_hw.h
@@ -2,10 +2,10 @@
* sound/awe_hw.h
*
* Access routines and definitions for the low level driver for the
- * AWE32/Sound Blaster 32 wave table synth.
- * version 0.4.2; Sep. 15, 1997
+ * Creative AWE32/SB32/AWE64 wave table synth.
+ * version 0.4.3; Mar. 1, 1998
*
- * Copyright (C) 1996,1997 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,16 +32,18 @@
#define awe_cmd_idx(reg,ch) (((reg)<< 5) | (ch))
-#define Data0 0x620 /* doubleword r/w */
-#define Data1 0xA20 /* doubleword r/w */
-#define Data2 0xA22 /* word r/w */
-#define Data3 0xE20 /* word r/w */
-#define Pointer 0xE22 /* register pointer r/w */
+#define Data0 0 /* 0x620: doubleword r/w */
+#define Data1 1 /* 0xA20: doubleword r/w */
+#define Data2 2 /* 0xA22: word r/w */
+#define Data3 3 /* 0xE20: word r/w */
+#define Pointer 4 /* 0xE22 register pointer r/w */
#define AWE_CPF(ch) awe_cmd_idx(0,ch), Data0 /* DW: current pitch and fractional address */
#define AWE_PTRX(ch) awe_cmd_idx(1,ch), Data0 /* DW: pitch target and reverb send */
#define AWE_CVCF(ch) awe_cmd_idx(2,ch), Data0 /* DW: current volume and filter cutoff */
#define AWE_VTFT(ch) awe_cmd_idx(3,ch), Data0 /* DW: volume and filter cutoff targets */
+#define AWE_0080(ch) awe_cmd_idx(4,ch), Data0 /* DW: ?? */
+#define AWE_00A0(ch) awe_cmd_idx(5,ch), Data0 /* DW: ?? */
#define AWE_PSST(ch) awe_cmd_idx(6,ch), Data0 /* DW: pan send and loop start address */
#define AWE_CSL(ch) awe_cmd_idx(7,ch), Data0 /* DW: chorus send and loop end address */
#define AWE_CCCA(ch) awe_cmd_idx(0,ch), Data1 /* DW: Q, control bits, and current address */
@@ -94,7 +96,4 @@
#define AWE_DRAM_OFFSET 0x200000
#define AWE_MAX_DRAM_SIZE (28 * 1024) /* 28 MB is max onboard memory */
-#define AWE_DEFAULT_ATTENUATION 32 /* 12dB below */
-#define AWE_DEFAULT_MOD_SENSE 18
-
#endif
diff --git a/drivers/sound/lowlevel/awe_version.h b/drivers/sound/lowlevel/awe_version.h
index c1de31715..a012d734a 100644
--- a/drivers/sound/lowlevel/awe_version.h
+++ b/drivers/sound/lowlevel/awe_version.h
@@ -1,13 +1,35 @@
+/*
+ * sound/awe_version.h
+ *
+ * Version defines for the AWE32/SB32/AWE64 wave table synth driver.
+ * version 0.4.3; Mar. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ */
+
/* AWE32 driver version number */
#ifndef AWE_VERSION_H_DEF
#define AWE_VERSION_H_DEF
-#define AWE_VERSION_NUMBER 0x00040203
-#define AWEDRV_VERSION "0.4.2c"
-#define AWE_MAJOR_VERSION(id) (((id) >> 16) & 0xff)
-#define AWE_MINOR_VERSION(id) (((id) >> 8) & 0xff)
-#define AWE_TINY_VERSION(id) ((id) & 0xff)
+#define AWE_MAJOR_VERSION 0
+#define AWE_MINOR_VERSION 4
+#define AWE_TINY_VERSION 3
+#define AWE_VERSION_NUMBER ((AWE_MAJOR_VERSION<<16)|(AWE_MINOR_VERSION<<8)|AWE_TINY_VERSION)
+#define AWEDRV_VERSION "0.4.3"
#endif
-
diff --git a/drivers/sound/lowlevel/awe_voice.h b/drivers/sound/lowlevel/awe_voice.h
deleted file mode 100644
index aa1313131..000000000
--- a/drivers/sound/lowlevel/awe_voice.h
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * sound/awe_voice.h
- *
- * Voice information definitions for the low level driver for the
- * AWE32/Sound Blaster 32 wave table synth.
- * version 0.4.2c; Oct. 7, 1997
- *
- * Copyright (C) 1996,1997 Takashi Iwai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef AWE_VOICE_H
-#define AWE_VOICE_H
-
-#ifndef SAMPLE_TYPE_AWE32
-#define SAMPLE_TYPE_AWE32 0x20
-#endif
-
-#ifndef _PATCHKEY
-#define _PATCHKEY(id) ((id<<8)|0xfd)
-#endif
-
-/*----------------------------------------------------------------
- * patch information record
- *----------------------------------------------------------------*/
-
-/* patch interface header: 16 bytes */
-typedef struct awe_patch_info {
- short key; /* use AWE_PATCH here */
-#define AWE_PATCH _PATCHKEY(0x07)
-
- short device_no; /* synthesizer number */
- unsigned short sf_id; /* file id (should be zero) */
- short optarg; /* optional argument */
- int len; /* data length (without this header) */
-
- short type; /* patch operation type */
-#define AWE_LOAD_INFO 0 /* awe_voice_rec */
-#define AWE_LOAD_DATA 1 /* awe_sample_info */
-#define AWE_OPEN_PATCH 2 /* awe_open_parm */
-#define AWE_CLOSE_PATCH 3 /* none */
-#define AWE_UNLOAD_PATCH 4 /* none */
-#define AWE_REPLACE_DATA 5 /* awe_sample_info (optarg=#channels)*/
-#define AWE_MAP_PRESET 6 /* awe_voice_map */
-#define AWE_LOAD_CHORUS_FX 0x10 /* awe_chorus_fx_rec (optarg=mode) */
-#define AWE_LOAD_REVERB_FX 0x11 /* awe_reverb_fx_rec (optarg=mode) */
-
- short reserved; /* word alignment data */
-
- /* the actual patch data begins after this */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
- char data[0];
-#endif
-} awe_patch_info;
-
-/*#define AWE_PATCH_INFO_SIZE 16*/
-#define AWE_PATCH_INFO_SIZE sizeof(awe_patch_info)
-
-
-/*----------------------------------------------------------------
- * open patch
- *----------------------------------------------------------------*/
-
-#define AWE_PATCH_NAME_LEN 32
-
-typedef struct _awe_open_parm {
- unsigned short type; /* sample type */
-#define AWE_PAT_TYPE_MISC 0
-#define AWE_PAT_TYPE_GM 1
-#define AWE_PAT_TYPE_GS 2
-#define AWE_PAT_TYPE_MT32 3
-#define AWE_PAT_TYPE_XG 4
-#define AWE_PAT_TYPE_SFX 5
-#define AWE_PAT_TYPE_GUS 6
-#define AWE_PAT_TYPE_MAP 7
-
-#define AWE_PAT_LOCKED 0x100 /* lock the samples */
-
- short reserved;
- char name[AWE_PATCH_NAME_LEN];
-} awe_open_parm;
-
-/*#define AWE_OPEN_PARM_SIZE 28*/
-#define AWE_OPEN_PARM_SIZE sizeof(awe_open_parm)
-
-
-/*----------------------------------------------------------------
- * raw voice information record
- *----------------------------------------------------------------*/
-
-/* wave table envelope & effect parameters to control EMU8000 */
-typedef struct _awe_voice_parm {
- unsigned short moddelay; /* modulation delay (0x8000) */
- unsigned short modatkhld; /* modulation attack & hold time (0x7f7f) */
- unsigned short moddcysus; /* modulation decay & sustain (0x7f7f) */
- unsigned short modrelease; /* modulation release time (0x807f) */
- short modkeyhold, modkeydecay; /* envelope change per key (not used) */
- unsigned short voldelay; /* volume delay (0x8000) */
- unsigned short volatkhld; /* volume attack & hold time (0x7f7f) */
- unsigned short voldcysus; /* volume decay & sustain (0x7f7f) */
- unsigned short volrelease; /* volume release time (0x807f) */
- short volkeyhold, volkeydecay; /* envelope change per key (not used) */
- unsigned short lfo1delay; /* LFO1 delay (0x8000) */
- unsigned short lfo2delay; /* LFO2 delay (0x8000) */
- unsigned short pefe; /* modulation pitch & cutoff (0x0000) */
- unsigned short fmmod; /* LFO1 pitch & cutoff (0x0000) */
- unsigned short tremfrq; /* LFO1 volume & freq (0x0000) */
- unsigned short fm2frq2; /* LFO2 pitch & freq (0x0000) */
- unsigned char cutoff; /* initial cutoff (0xff) */
- unsigned char filterQ; /* initial filter Q [0-15] (0x0) */
- unsigned char chorus; /* chorus send (0x00) */
- unsigned char reverb; /* reverb send (0x00) */
- unsigned short reserved[4]; /* not used */
-} awe_voice_parm;
-
-#define AWE_VOICE_PARM_SIZE 48
-
-
-/* wave table parameters: 92 bytes */
-typedef struct _awe_voice_info {
- unsigned short sf_id; /* file id (should be zero) */
- unsigned short sample; /* sample id */
- int start, end; /* sample offset correction */
- int loopstart, loopend; /* loop offset correction */
- short rate_offset; /* sample rate pitch offset */
- unsigned short mode; /* sample mode */
-#define AWE_MODE_ROMSOUND 0x8000
-#define AWE_MODE_STEREO 1
-#define AWE_MODE_LOOPING 2
-#define AWE_MODE_NORELEASE 4 /* obsolete */
-#define AWE_MODE_INIT_PARM 8
-
- short root; /* midi root key */
- short tune; /* pitch tuning (in cents) */
- char low, high; /* key note range */
- char vellow, velhigh; /* velocity range */
- char fixkey, fixvel; /* fixed key, velocity */
- char pan, fixpan; /* panning, fixed panning */
- short exclusiveClass; /* exclusive class (0 = none) */
- unsigned char amplitude; /* sample volume (127 max) */
- unsigned char attenuation; /* attenuation (0.375dB) */
- short scaleTuning; /* pitch scale tuning(%), normally 100 */
- awe_voice_parm parm; /* voice envelope parameters */
- short index; /* internal index (set by driver) */
-} awe_voice_info;
-
-/*#define AWE_VOICE_INFO_SIZE 92*/
-#define AWE_VOICE_INFO_SIZE sizeof(awe_voice_info)
-
-/*----------------------------------------------------------------*/
-
-/* The info entry of awe_voice_rec is changed from 0 to 1
- * for some compilers refusing zero size array.
- * Due to this change, sizeof(awe_voice_rec) becomes different
- * from older versions.
- * Use AWE_VOICE_REC_SIZE instead.
- */
-
-/* instrument info header: 4 bytes */
-typedef struct _awe_voice_rec_hdr {
- unsigned char bank; /* midi bank number */
- unsigned char instr; /* midi preset number */
- char nvoices; /* number of voices */
- char write_mode; /* write mode; normally 0 */
-#define AWE_WR_APPEND 0 /* append anyway */
-#define AWE_WR_EXCLUSIVE 1 /* skip if already exists */
-#define AWE_WR_REPLACE 2 /* replace if already exists */
-} awe_voice_rec_hdr;
-
-/*#define AWE_VOICE_REC_SIZE 4*/
-#define AWE_VOICE_REC_SIZE sizeof(awe_voice_rec_hdr)
-
-/* the standard patch structure for one sample */
-typedef struct _awe_voice_rec_patch {
- awe_patch_info patch;
- awe_voice_rec_hdr hdr;
- awe_voice_info info;
-} awe_voice_rec_patch;
-
-
-/* obsolete data type */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-#define AWE_INFOARRAY_SIZE 0
-#else
-#define AWE_INFOARRAY_SIZE 1
-#endif
-
-typedef struct _awe_voice_rec {
- unsigned char bank; /* midi bank number */
- unsigned char instr; /* midi preset number */
- short nvoices; /* number of voices */
- /* voice information follows here */
- awe_voice_info info[AWE_INFOARRAY_SIZE];
-} awe_voice_rec;
-
-
-/*----------------------------------------------------------------
- * sample wave information
- *----------------------------------------------------------------*/
-
-/* wave table sample header: 32 bytes */
-typedef struct awe_sample_info {
- unsigned short sf_id; /* file id (should be zero) */
- unsigned short sample; /* sample id */
- int start, end; /* start & end offset */
- int loopstart, loopend; /* loop start & end offset */
- int size; /* size (0 = ROM) */
- short checksum_flag; /* use check sum = 1 */
- unsigned short mode_flags; /* mode flags */
-#define AWE_SAMPLE_8BITS 1 /* wave data is 8bits */
-#define AWE_SAMPLE_UNSIGNED 2 /* wave data is unsigned */
-#define AWE_SAMPLE_NO_BLANK 4 /* no blank loop is attached */
-#define AWE_SAMPLE_SINGLESHOT 8 /* single-shot w/o loop */
-#define AWE_SAMPLE_BIDIR_LOOP 16 /* bidirectional looping */
-#define AWE_SAMPLE_STEREO_LEFT 32 /* stereo left sound */
-#define AWE_SAMPLE_STEREO_RIGHT 64 /* stereo right sound */
-#define AWE_SAMPLE_REVERSE_LOOP 128 /* reverse looping */
- unsigned int checksum; /* check sum */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
- unsigned short data[0]; /* sample data follows here */
-#endif
-} awe_sample_info;
-
-/*#define AWE_SAMPLE_INFO_SIZE 32*/
-#define AWE_SAMPLE_INFO_SIZE sizeof(awe_sample_info)
-
-
-/*----------------------------------------------------------------
- * voice preset mapping
- *----------------------------------------------------------------*/
-
-typedef struct awe_voice_map {
- int map_bank, map_instr, map_key; /* key = -1 means all keys */
- int src_bank, src_instr, src_key;
-} awe_voice_map;
-
-#define AWE_VOICE_MAP_SIZE sizeof(awe_voice_map)
-
-
-/*----------------------------------------------------------------
- * awe hardware controls
- *----------------------------------------------------------------*/
-
-#define _AWE_DEBUG_MODE 0x00
-#define _AWE_REVERB_MODE 0x01
-#define _AWE_CHORUS_MODE 0x02
-#define _AWE_REMOVE_LAST_SAMPLES 0x03
-#define _AWE_INITIALIZE_CHIP 0x04
-#define _AWE_SEND_EFFECT 0x05
-#define _AWE_TERMINATE_CHANNEL 0x06
-#define _AWE_TERMINATE_ALL 0x07
-#define _AWE_INITIAL_VOLUME 0x08
-#define _AWE_INITIAL_ATTEN _AWE_INITIAL_VOLUME
-#define _AWE_RESET_CHANNEL 0x09
-#define _AWE_CHANNEL_MODE 0x0a
-#define _AWE_DRUM_CHANNELS 0x0b
-#define _AWE_MISC_MODE 0x0c
-#define _AWE_RELEASE_ALL 0x0d
-#define _AWE_NOTEOFF_ALL 0x0e
-#define _AWE_CHN_PRESSURE 0x0f
-/*#define _AWE_GET_CURRENT_MODE 0x10*/
-#define _AWE_EQUALIZER 0x11
-/*#define _AWE_GET_MISC_MODE 0x12*/
-/*#define _AWE_GET_FONTINFO 0x13*/
-
-#define _AWE_MODE_FLAG 0x80
-#define _AWE_COOKED_FLAG 0x40 /* not supported */
-#define _AWE_MODE_VALUE_MASK 0x3F
-
-/*----------------------------------------------------------------*/
-
-#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \
-{((char*)(p))[0] = SEQ_PRIVATE;\
- ((char*)(p))[1] = dev;\
- ((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\
- ((char*)(p))[3] = voice;\
- ((unsigned short*)(p))[2] = p1;\
- ((unsigned short*)(p))[3] = p2;}
-
-/* buffered access */
-#define _AWE_CMD(dev, voice, cmd, p1, p2) \
-{_SEQ_NEEDBUF(8);\
- _AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\
- _SEQ_ADVBUF(8);}
-
-/* direct access */
-#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \
-{struct seq_event_rec tmp;\
- _AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\
- ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);}
-
-/*----------------------------------------------------------------*/
-
-/* set debugging mode */
-#define AWE_DEBUG_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
-/* set reverb mode; from 0 to 7 */
-#define AWE_REVERB_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
-/* set chorus mode; from 0 to 7 */
-#define AWE_CHORUS_MODE(dev,p1) _AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
-
-/* reset channel */
-#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0)
-#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0)
-
-/* send an effect to all layers */
-#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
-#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value)
-#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0)
-/* send an effect to a layer */
-#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value)
-#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value)
-#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0)
-
-/* terminate sound on the channel/voice */
-#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
-/* terminate all sounds */
-#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
-/* release all sounds (w/o sustain effect) */
-#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0)
-/* note off all sounds (w sustain effect) */
-#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0)
-
-/* set initial attenuation */
-#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
-#define AWE_INITIAL_ATTEN AWE_INITIAL_VOLUME
-/* relative attenuation */
-#define AWE_SET_ATTEN(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1)
-
-/* set channel playing mode; mode=0/1/2 */
-#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0)
-#define AWE_PLAY_INDIRECT 0 /* indirect voice mode (default) */
-#define AWE_PLAY_MULTI 1 /* multi note voice mode */
-#define AWE_PLAY_DIRECT 2 /* direct single voice mode */
-#define AWE_PLAY_MULTI2 3 /* sequencer2 mode; used internally */
-
-/* set drum channel mask; channels is 32bit long value */
-#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16))
-
-/* set bass and treble control; values are from 0 to 11 */
-#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble)
-
-/* remove last loaded samples */
-#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
-/* initialize emu8000 chip */
-#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
-
-/* set miscellaneous modes; meta command */
-#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value)
-/* exclusive sound off; 1=off */
-#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode)
-/* default GUS bank number */
-#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank)
-/* change panning position in realtime; 0=don't 1=do */
-#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode)
-
-/* extended pressure controls; not portable with other sound drivers */
-#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel)
-#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0)
-
-/*----------------------------------------------------------------*/
-
-/* reverb mode parameters */
-#define AWE_REVERB_ROOM1 0
-#define AWE_REVERB_ROOM2 1
-#define AWE_REVERB_ROOM3 2
-#define AWE_REVERB_HALL1 3
-#define AWE_REVERB_HALL2 4
-#define AWE_REVERB_PLATE 5
-#define AWE_REVERB_DELAY 6
-#define AWE_REVERB_PANNINGDELAY 7
-#define AWE_REVERB_PREDEFINED 8
-/* user can define reverb modes up to 32 */
-#define AWE_REVERB_NUMBERS 32
-
-typedef struct awe_reverb_fx_rec {
- unsigned short parms[28];
-} awe_reverb_fx_rec;
-
-/*----------------------------------------------------------------*/
-
-/* chorus mode parameters */
-#define AWE_CHORUS_1 0
-#define AWE_CHORUS_2 1
-#define AWE_CHORUS_3 2
-#define AWE_CHORUS_4 3
-#define AWE_CHORUS_FEEDBACK 4
-#define AWE_CHORUS_FLANGER 5
-#define AWE_CHORUS_SHORTDELAY 6
-#define AWE_CHORUS_SHORTDELAY2 7
-#define AWE_CHORUS_PREDEFINED 8
-/* user can define chorus modes up to 32 */
-#define AWE_CHORUS_NUMBERS 32
-
-typedef struct awe_chorus_fx_rec {
- unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
- unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
- unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
- unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
- unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
-} awe_chorus_fx_rec;
-
-/*----------------------------------------------------------------*/
-
-/* misc mode types */
-enum {
-/* 0*/ AWE_MD_EXCLUSIVE_OFF, /* obsolete */
-/* 1*/ AWE_MD_EXCLUSIVE_ON, /* obsolete */
-/* 2*/ AWE_MD_VERSION, /* read only */
-/* 3*/ AWE_MD_EXCLUSIVE_SOUND, /* ignored */
-/* 4*/ AWE_MD_REALTIME_PAN, /* 0/1: do realtime pan change (default=1) */
-/* 5*/ AWE_MD_GUS_BANK, /* bank number for GUS patches (default=0) */
-/* 6*/ AWE_MD_KEEP_EFFECT, /* 0/1: keep effect values, (default=0) */
-/* 7*/ AWE_MD_ZERO_ATTEN, /* attenuation of max volume (default=32) */
-/* 8*/ AWE_MD_CHN_PRIOR, /* 0/1: set MIDI channel priority mode (default=1) */
-/* 9*/ AWE_MD_MOD_SENSE, /* integer: modwheel sensitivity (def=18) */
-/*10*/ AWE_MD_DEF_PRESET, /* integer: default preset number (def=0) */
-/*11*/ AWE_MD_DEF_BANK, /* integer: default bank number (def=0) */
-/*12*/ AWE_MD_DEF_DRUM, /* integer: default drumset number (def=0) */
-/*13*/ AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */
- AWE_MD_END,
-};
-
-/*----------------------------------------------------------------*/
-
-/* effect parameters */
-enum {
-
-/* modulation envelope parameters */
-/* 0*/ AWE_FX_ENV1_DELAY, /* WORD: ENVVAL */
-/* 1*/ AWE_FX_ENV1_ATTACK, /* BYTE: up ATKHLD */
-/* 2*/ AWE_FX_ENV1_HOLD, /* BYTE: lw ATKHLD */
-/* 3*/ AWE_FX_ENV1_DECAY, /* BYTE: lw DCYSUS */
-/* 4*/ AWE_FX_ENV1_RELEASE, /* BYTE: lw DCYSUS */
-/* 5*/ AWE_FX_ENV1_SUSTAIN, /* BYTE: up DCYSUS */
-/* 6*/ AWE_FX_ENV1_PITCH, /* BYTE: up PEFE */
-/* 7*/ AWE_FX_ENV1_CUTOFF, /* BYTE: lw PEFE */
-
-/* volume envelope parameters */
-/* 8*/ AWE_FX_ENV2_DELAY, /* WORD: ENVVOL */
-/* 9*/ AWE_FX_ENV2_ATTACK, /* BYTE: up ATKHLDV */
-/*10*/ AWE_FX_ENV2_HOLD, /* BYTE: lw ATKHLDV */
-/*11*/ AWE_FX_ENV2_DECAY, /* BYTE: lw DCYSUSV */
-/*12*/ AWE_FX_ENV2_RELEASE, /* BYTE: lw DCYSUSV */
-/*13*/ AWE_FX_ENV2_SUSTAIN, /* BYTE: up DCYSUSV */
-
-/* LFO1 (tremolo & vibrato) parameters */
-/*14*/ AWE_FX_LFO1_DELAY, /* WORD: LFO1VAL */
-/*15*/ AWE_FX_LFO1_FREQ, /* BYTE: lo TREMFRQ */
-/*16*/ AWE_FX_LFO1_VOLUME, /* BYTE: up TREMFRQ */
-/*17*/ AWE_FX_LFO1_PITCH, /* BYTE: up FMMOD */
-/*18*/ AWE_FX_LFO1_CUTOFF, /* BYTE: lo FMMOD */
-
-/* LFO2 (vibrato) parameters */
-/*19*/ AWE_FX_LFO2_DELAY, /* WORD: LFO2VAL */
-/*20*/ AWE_FX_LFO2_FREQ, /* BYTE: lo FM2FRQ2 */
-/*21*/ AWE_FX_LFO2_PITCH, /* BYTE: up FM2FRQ2 */
-
-/* Other overall effect parameters */
-/*22*/ AWE_FX_INIT_PITCH, /* SHORT: pitch offset */
-/*23*/ AWE_FX_CHORUS, /* BYTE: chorus effects send (0-255) */
-/*24*/ AWE_FX_REVERB, /* BYTE: reverb effects send (0-255) */
-/*25*/ AWE_FX_CUTOFF, /* BYTE: up IFATN */
-/*26*/ AWE_FX_FILTERQ, /* BYTE: up CCCA */
-
-/* Sample / loop offset changes */
-/*27*/ AWE_FX_SAMPLE_START, /* SHORT: offset */
-/*28*/ AWE_FX_LOOP_START, /* SHORT: offset */
-/*29*/ AWE_FX_LOOP_END, /* SHORT: offset */
-/*30*/ AWE_FX_COARSE_SAMPLE_START, /* SHORT: upper word offset */
-/*31*/ AWE_FX_COARSE_LOOP_START, /* SHORT: upper word offset */
-/*32*/ AWE_FX_COARSE_LOOP_END, /* SHORT: upper word offset */
-/*33*/ AWE_FX_ATTEN, /* BYTE: lo IFATN */
-
- AWE_FX_END,
-};
-
-#endif /* AWE_VOICE_H */
diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c
index 111b0c5be..1c2472049 100644
--- a/drivers/sound/lowlevel/awe_wave.c
+++ b/drivers/sound/lowlevel/awe_wave.c
@@ -1,10 +1,10 @@
/*
* sound/awe_wave.c
*
- * The low level driver for the AWE32/Sound Blaster 32 wave table synth.
- * version 0.4.2c; Oct. 7, 1997
+ * The low level driver for the AWE32/SB32/AWE64 wave table synth.
+ * version 0.4.3; Nov. 1, 1998
*
- * Copyright (C) 1996,1997 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
*
* This 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,62 +21,27 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+/* include initial header files and compatibility macros */
#ifdef __FreeBSD__
-# include <i386/isa/sound/awe_config.h>
+# include <i386/isa/sound/awe_compat.h>
#else
-#ifdef MODULE
-#include <linux/config.h>
-#include <linux/string.h>
-#include <linux/module.h>
-# include "../soundmodule.h"
-#endif
-# include "awe_config.h"
+# include "awe_compat.h"
+#endif /* FreeBSD */
+#ifdef __linux__
+# include <linux/config.h>
#endif
/*----------------------------------------------------------------*/
#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
-#ifdef __FreeBSD__
-# include <i386/isa/sound/awe_hw.h>
-# include <i386/isa/sound/awe_version.h>
-# include <i386/isa/sound/awe_voice.h>
-#else
-# include "awe_hw.h"
-# include "awe_version.h"
-# include <linux/awe_voice.h>
-#endif
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-/* include fine tuning table */
-#ifdef AWE_OBSOLETE_VOXWARE
-# ifdef __FreeBSD__
-# define SEQUENCER_C
-# include <i386/isa/sound/tuning.h>
-# else
-# include "tuning.h"
-# endif
-#else
-# include "../tuning.h"
-#endif
-
-#ifdef linux
-# include <linux/ultrasound.h>
-#elif defined(__FreeBSD__)
-# include <machine/ultrasound.h>
-#endif
-
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
/*----------------------------------------------------------------
* debug message
*----------------------------------------------------------------*/
-static int debug_mode = 0;
#ifdef AWE_DEBUG_ON
-#define DEBUG(LVL,XXX) {if (debug_mode > LVL) { XXX; }}
-#define ERRMSG(XXX) {if (debug_mode) { XXX; }}
+#define DEBUG(LVL,XXX) {if (ctrls[AWE_MD_DEBUG_MODE] > LVL) { XXX; }}
+#define ERRMSG(XXX) {if (ctrls[AWE_MD_DEBUG_MODE]) { XXX; }}
#define FATALERR(XXX) XXX
#else
#define DEBUG(LVL,XXX) /**/
@@ -97,7 +62,10 @@ typedef struct _sf_list {
int mem_ptr; /* current word byte pointer */
int infos;
int samples;
- /*char name[AWE_PATCH_NAME_LEN];*/
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ int shared; /* shared index */
+ unsigned char name[AWE_PATCH_NAME_LEN];
+#endif
} sf_list;
/* bank record */
@@ -203,10 +171,12 @@ typedef struct _voice_info {
int apitch; /* pitch parameter */
int avol; /* volume parameter */
int apan; /* panning parameter */
+ int acutoff; /* cutoff parameter */
+ short aaux; /* aux word */
} voice_info;
/* voice information */
-static voice_info *voices;
+static voice_info voices[AWE_MAX_VOICES];
#define IS_NO_SOUND(v) (voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED))
#define IS_NO_EFFECT(v) (voices[v].state != AWE_ST_ON)
@@ -215,7 +185,7 @@ static voice_info *voices;
/* MIDI channel effects information (for hw control) */
-static awe_chan_info *channels;
+static awe_chan_info channels[AWE_MAX_CHANNELS];
/*----------------------------------------------------------------
@@ -227,13 +197,23 @@ static awe_chan_info *channels;
#endif
#ifndef AWE_DEFAULT_MEM_SIZE
-#define AWE_DEFAULT_MEM_SIZE 0 /* autodetect */
+#define AWE_DEFAULT_MEM_SIZE -1 /* autodetect */
#endif
+/* set variables */
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+/* replace awe_port variable with exported variable */
+#define awe_port io
+#define BASEVAR_DECL /**/
+#else
+#define BASEVAR_DECL static
+#endif /* module */
+
/* awe32 base address (overwritten at initialization) */
-static int awe_base = AWE_DEFAULT_BASE_ADDR;
+BASEVAR_DECL int awe_port = AWE_DEFAULT_BASE_ADDR;
/* memory byte size */
-static int awe_mem_size = AWE_DEFAULT_MEM_SIZE;
+BASEVAR_DECL int memsize = AWE_DEFAULT_MEM_SIZE; /* for module option */
+static int awe_mem_size = -1;
/* DRAM start offset */
static int awe_mem_start = AWE_DRAM_OFFSET;
@@ -242,15 +222,13 @@ static int awe_max_voices = AWE_MAX_VOICES;
static int patch_opened = 0; /* sample already loaded? */
-static int reverb_mode = 4; /* reverb mode */
-static int chorus_mode = 2; /* chorus mode */
-static short init_atten = AWE_DEFAULT_ATTENUATION; /* 12dB below */
+static char atten_relative = FALSE;
+static short atten_offset = 0;
static int awe_present = FALSE; /* awe device present? */
static int awe_busy = FALSE; /* awe device opened? */
static int my_dev = -1;
-static int my_mixerdev = -1 ;
#define DEFAULT_DRUM_FLAGS ((1 << 9) | (1 << 25))
#define IS_DRUM_CHANNEL(c) (drum_flags & (1 << (c)))
@@ -264,31 +242,6 @@ static int playing_mode = AWE_PLAY_INDIRECT;
static int current_alloc_time = 0; /* voice allocation index for channel mode */
-static struct MiscModeDef {
- int value;
- int init_each_time;
-} misc_modes_default[AWE_MD_END] = {
- {0,0}, {0,0}, /* <-- not used */
- {AWE_VERSION_NUMBER, FALSE},
- {TRUE, TRUE}, /* exclusive */
- {TRUE, TRUE}, /* realpan */
- {AWE_DEFAULT_BANK, TRUE}, /* gusbank */
- {FALSE, TRUE}, /* keep effect */
- {AWE_DEFAULT_ATTENUATION, FALSE}, /* zero_atten */
- {FALSE, TRUE}, /* chn_prior */
- {AWE_DEFAULT_MOD_SENSE, TRUE}, /* modwheel sense */
- {AWE_DEFAULT_PRESET, TRUE}, /* def_preset */
- {AWE_DEFAULT_BANK, TRUE}, /* def_bank */
- {AWE_DEFAULT_DRUM, TRUE}, /* def_drum */
- {FALSE, TRUE}, /* toggle_drum_bank */
-};
-
-static int misc_modes[AWE_MD_END];
-
-static int awe_bass_level = 5;
-static int awe_treble_level = 9;
-
-
static struct synth_info awe_info = {
"AWE32 Synth", /* name */
0, /* device */
@@ -308,14 +261,15 @@ static struct voice_alloc_info *voice_alloc; /* set at initialization */
* function prototypes
*----------------------------------------------------------------*/
-#ifndef AWE_OBSOLETE_VOXWARE
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
static int awe_check_port(void);
static void awe_request_region(void);
static void awe_release_region(void);
-#endif
+#endif /* linux & obsolete */
static void awe_reset_samples(void);
/* emu8000 chip i/o access */
+static void setup_ports(int p1, int p2, int p3);
static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);
static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data);
static unsigned short awe_peek(unsigned short cmd, unsigned short port);
@@ -323,10 +277,12 @@ static unsigned int awe_peek_dw(unsigned short cmd, unsigned short port);
static void awe_wait(unsigned short delay);
/* initialize emu8000 chip */
+static int _attach_awe(void);
+static void _unload_awe(void);
static void awe_initialize(void);
/* set voice parameters */
-static void awe_init_misc_modes(int init_all);
+static void awe_init_ctrl_parms(int init_all);
static void awe_init_voice_info(awe_voice_info *vp);
static void awe_init_voice_parm(awe_voice_parm *pp);
#ifdef AWE_HAS_GUS_COMPATIBILITY
@@ -337,7 +293,7 @@ static int calc_parm_hold(int msec);
static int calc_parm_attack(int msec);
static int calc_parm_decay(int msec);
static int calc_parm_search(int msec, short *table);
-#endif
+#endif /* gus compat */
/* turn on/off note */
static void awe_note_on(int voice);
@@ -362,9 +318,13 @@ static void awe_calc_pitch(int voice);
static void awe_calc_pitch_from_freq(int voice, int freq);
#endif
static void awe_calc_volume(int voice);
+static void awe_update_volume(void);
+static void awe_change_master_volume(short val);
static void awe_voice_init(int voice, int init_all);
static void awe_channel_init(int ch, int init_all);
static void awe_fx_init(int ch);
+static void awe_send_effect(int voice, int layer, int type, int val);
+static void awe_modwheel_change(int voice, int value);
/* sequencer interface */
static int awe_open(int dev, int mode);
@@ -389,6 +349,8 @@ static void awe_bender(int dev, int voice, int value);
static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);
static void awe_setup_voice(int dev, int voice, int chn);
+#define awe_key_pressure(dev,voice,key,press) awe_start_note(dev,voice,(key)+128,press)
+
/* hardware controls */
#ifdef AWE_HAS_GUS_COMPATIBILITY
static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
@@ -417,6 +379,8 @@ static int awe_load_map(awe_patch_info *patch, const char *addr, int count);
#ifdef AWE_HAS_GUS_COMPATIBILITY
static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
#endif
+/*static int awe_probe_info(awe_patch_info *patch, const char *addr, int count);*/
+static int awe_probe_data(awe_patch_info *patch, const char *addr, int count);
static int check_patch_opened(int type, char *name);
static int awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels);
static void add_sf_info(int rec);
@@ -426,6 +390,14 @@ static void add_info_list(int rec);
static void awe_remove_samples(int sf_id);
static void rebuild_preset_list(void);
static short awe_set_sample(awe_voice_info *vp);
+static int search_sample_index(int sf, int sample, int level);
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+static int is_identical_id(int id1, int id2);
+static int is_identical_name(unsigned char *name, int id);
+static int is_shared_sf(unsigned char *name);
+static int info_duplicated(awe_voice_list *rec);
+#endif /* allow sharing */
/* lowlevel functions */
static void awe_init_audio(void);
@@ -441,24 +413,83 @@ static void awe_close_dram(void);
static void awe_write_dram(unsigned short c);
static int awe_detect_base(int addr);
static int awe_detect(void);
-static int awe_check_dram(void);
+static void awe_check_dram(void);
static int awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count);
static void awe_set_chorus_mode(int mode);
+static void awe_update_chorus_mode(void);
static int awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count);
static void awe_set_reverb_mode(int mode);
+static void awe_update_reverb_mode(void);
static void awe_equalizer(int bass, int treble);
+static void awe_update_equalizer(void);
+
#ifdef CONFIG_AWE32_MIXER
-static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg);
+static void attach_mixer(void);
+static void unload_mixer(void);
#endif
-/* define macros for compatibility */
+#ifdef CONFIG_AWE32_MIDIEMU
+static void attach_midiemu(void);
+static void unload_midiemu(void);
+#endif
+
+#define limitvalue(x, a, b) if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b)
+
#ifdef __FreeBSD__
-# include <i386/isa/sound/awe_compat.h>
-#else
-# include "awe_compat.h"
+/* FIXME */
+#define MALLOC_LOOP_DATA
+#define WAIT_BY_LOOP
#endif
/*----------------------------------------------------------------
+ * control parameters
+ *----------------------------------------------------------------*/
+
+
+#ifdef AWE_USE_NEW_VOLUME_CALC
+#define DEF_VOLUME_CALC TRUE
+#else
+#define DEF_VOLUME_CALC FALSE
+#endif /* new volume */
+
+#define DEF_ZERO_ATTEN 32 /* 12dB below */
+#define DEF_MOD_SENSE 18
+#define DEF_CHORUS_MODE 2
+#define DEF_REVERB_MODE 4
+#define DEF_BASS_LEVEL 5
+#define DEF_TREBLE_LEVEL 9
+
+static struct CtrlParmsDef {
+ int value;
+ int init_each_time;
+ void (*update)(void);
+} ctrl_parms[AWE_MD_END] = {
+ {0,0, NULL}, {0,0, NULL}, /* <-- not used */
+ {AWE_VERSION_NUMBER, FALSE, NULL},
+ {TRUE, FALSE, NULL}, /* exclusive */
+ {TRUE, FALSE, NULL}, /* realpan */
+ {AWE_DEFAULT_BANK, FALSE, NULL}, /* gusbank */
+ {FALSE, TRUE, NULL}, /* keep effect */
+ {DEF_ZERO_ATTEN, FALSE, awe_update_volume}, /* zero_atten */
+ {FALSE, FALSE, NULL}, /* chn_prior */
+ {DEF_MOD_SENSE, FALSE, NULL}, /* modwheel sense */
+ {AWE_DEFAULT_PRESET, FALSE, NULL}, /* def_preset */
+ {AWE_DEFAULT_BANK, FALSE, NULL}, /* def_bank */
+ {AWE_DEFAULT_DRUM, FALSE, NULL}, /* def_drum */
+ {FALSE, FALSE, NULL}, /* toggle_drum_bank */
+ {DEF_VOLUME_CALC, FALSE, awe_update_volume}, /* new_volume_calc */
+ {DEF_CHORUS_MODE, FALSE, awe_update_chorus_mode}, /* chorus mode */
+ {DEF_REVERB_MODE, FALSE, awe_update_reverb_mode}, /* reverb mode */
+ {DEF_BASS_LEVEL, FALSE, awe_update_equalizer}, /* bass level */
+ {DEF_TREBLE_LEVEL, FALSE, awe_update_equalizer}, /* treble level */
+ {0, FALSE, NULL}, /* debug mode */
+ {FALSE, FALSE, NULL}, /* pan exchange */
+};
+
+static int ctrls[AWE_MD_END];
+
+
+/*----------------------------------------------------------------
* synth operation table
*----------------------------------------------------------------*/
@@ -492,60 +523,34 @@ static struct synth_operations awe_operations =
awe_setup_voice
};
-#ifdef CONFIG_AWE32_MIXER
-static struct mixer_operations awe_mixer_operations = {
-#ifndef __FreeBSD__
- "AWE32",
-#endif
- "AWE32 Equalizer",
- awe_mixer_ioctl,
-};
-#endif
-
/*================================================================
- * attach / unload interface
+ * General attach / unload interface
*================================================================*/
-#ifdef AWE_OBSOLETE_VOXWARE
-#define ATTACH_DECL static
-#else
-#define ATTACH_DECL /**/
-#endif
-
-ATTACH_DECL
-int attach_awe(void)
+static int _attach_awe(void)
{
+ if (awe_present) return 0; /* for OSS38.. called twice? */
+
/* check presence of AWE32 card */
if (! awe_detect()) {
- printk("AWE32: not detected\n");
+ printk(KERN_WARNING "AWE32: not detected\n");
return 0;
}
/* check AWE32 ports are available */
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
if (awe_check_port()) {
- printk("AWE32: I/O area already used.\n");
+ printk(KERN_WARNING "AWE32: I/O area already used.\n");
return 0;
}
+#endif
/* set buffers to NULL */
- voices = NULL;
- channels = NULL;
sflists = NULL;
samples = NULL;
infos = NULL;
- /* voice & channel info */
- voices = (voice_info*)my_malloc(AWE_MAX_VOICES * sizeof(voice_info));
- channels = (awe_chan_info*)my_malloc(AWE_MAX_CHANNELS * sizeof(awe_chan_info));
-
- if (voices == NULL || channels == NULL) {
- my_free(voices);
- my_free(channels);
- printk("AWE32: can't allocate sample tables\n");
- return 0;
- }
-
/* allocate sample tables */
INIT_TABLE(sflists, max_sfs, AWE_MAX_SF_LISTS, sf_list);
INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list);
@@ -553,8 +558,6 @@ int attach_awe(void)
my_dev = sound_alloc_synthdev();
if (my_dev == -1) {
- my_free(voices);
- my_free(channels);
printk(KERN_WARNING "AWE32 Error: too many synthesizers\n");
return 0;
}
@@ -564,13 +567,16 @@ int attach_awe(void)
synth_devs[my_dev] = &awe_operations;
#ifdef CONFIG_AWE32_MIXER
- if ((my_mixerdev=sound_alloc_mixerdev())!=-1) {
- mixer_devs[my_mixerdev] = &awe_mixer_operations;
- }
+ attach_mixer();
+#endif
+#ifdef CONFIG_AWE32_MIDIEMU
+ attach_midiemu();
#endif
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
/* reserve I/O ports for awedrv */
awe_request_region();
+#endif
/* clear all samples */
awe_reset_samples();
@@ -580,21 +586,14 @@ int attach_awe(void)
sprintf(awe_info.name, "AWE32-%s (RAM%dk)",
AWEDRV_VERSION, awe_mem_size/1024);
-#ifdef __FreeBSD__
- printk("awe0: <SoundBlaster EMU8000 MIDI (RAM%dk)>", awe_mem_size/1024);
-#elif defined(AWE_DEBUG_ON)
- printk("%s\n", awe_info.name);
-#endif
-
- /* set default values */
- awe_init_misc_modes(TRUE);
-
- /* set reverb & chorus modes */
- awe_set_reverb_mode(reverb_mode);
- awe_set_chorus_mode(chorus_mode);
+ printk("<SoundBlaster EMU8000 (RAM%dk)>\n", awe_mem_size/1024);
awe_present = TRUE;
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+ SOUND_LOCK;
+#endif
+
return 1;
}
@@ -602,48 +601,168 @@ int attach_awe(void)
#ifdef AWE_DYNAMIC_BUFFER
static void free_tables(void)
{
- my_free(sflists);
+ if (sflists)
+ my_free(sflists);
sflists = NULL; max_sfs = 0;
- my_free(samples);
+ if (samples)
+ my_free(samples);
samples = NULL; max_samples = 0;
- my_free(infos);
+ if (infos)
+ my_free(infos);
infos = NULL; max_infos = 0;
}
-#else
+
+static void *realloc_block(void *buf, int oldsize, int size)
+{
+ void *ptr;
+ if (oldsize == size)
+ return buf;
+ if ((ptr = my_malloc(size)) == NULL)
+ return NULL;
+ if (oldsize && size)
+ MEMCPY(ptr, buf, ((oldsize < size) ? oldsize : size) );
+ if (buf)
+ my_free(buf);
+ return ptr;
+}
+
+
+#else /* dynamic buffer */
+
#define free_buffers() /**/
-#endif
+#endif /* dynamic_buffer */
-ATTACH_DECL
-void unload_awe(void)
+
+static void _unload_awe(void)
{
if (awe_present) {
awe_reset_samples();
awe_release_region();
- my_free(voices);
- my_free(channels);
free_tables();
- sound_unload_mixerdev(my_mixerdev);
+#ifdef CONFIG_AWE32_MIXER
+ unload_mixer();
+#endif
+#ifdef CONFIG_AWE32_MIDIEMU
+ unload_midiemu();
+#endif
sound_unload_synthdev(my_dev);
awe_present = FALSE;
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+ SOUND_LOCK_END;
+#endif
+ }
+}
+
+
+/*================================================================
+ * Linux interface
+ *================================================================*/
+
+#ifdef linux
+
+/*----------------------------------------------------------------
+ * Linux PnP driver support
+ *----------------------------------------------------------------*/
+
+#ifdef CONFIG_PNP_DRV
+
+#include <linux/pnp.h>
+
+BASEVAR_DECL int pnp = 1; /* use PnP as default */
+
+#define AWE_NUM_CHIPS 3
+static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
+ PNP_EISAID('C','T','L',0x0021),
+ PNP_EISAID('C','T','L',0x0022),
+ PNP_EISAID('C','T','L',0x0023),
+};
+static struct pnp_driver pnp_awe[AWE_NUM_CHIPS];
+static int awe_pnp_ok = 0;
+
+static void awe_pnp_config(struct pnp_device *d)
+{
+ struct pnp_resource *r;
+ int port[3];
+ int nio = 0;
+
+ port[0] = port[1] = port[2] = 0;
+ for (r = d->res; r != NULL; r = r->next) {
+ if (r->type == PNP_RES_IO) {
+ if (nio >= 0 && nio < 3)
+ port[nio] = r->start;
+ nio++;
+ }
}
+ setup_ports(port[0], port[1], port[2]);
+ DEBUG(0,printk("AWE32: PnP setup ports: %x:%x:%x\n", port[0], port[1], port[2]));
}
+static int awe_pnp_event (struct pnp_device *d, struct pnp_drv_event *e)
+{
+ struct pnp_driver *drv = d->l.k.driver;
+
+ switch (e->type) {
+ case PNP_DRV_ALLOC:
+ drv->flags |= PNP_DRV_INUSE;
+ awe_pnp_ok = 1;
+ awe_pnp_config(d);
+ _attach_awe();
+ break;
+
+ case PNP_DRV_DISABLE:
+ case PNP_DRV_EMERGSTOP:
+ drv->flags &= ~PNP_DRV_INUSE;
+ awe_pnp_ok = 0;
+ _unload_awe();
+ break;
+
+ case PNP_DRV_CONFIG:
+ if (awe_busy) return 1; /* used now */
+ awe_release_region();
+ awe_pnp_config(d);
+ awe_request_region();
+ break;
+
+ case PNP_DRV_RECONFIG:
+ break;
+ }
+ return 0;
+}
+
+static int awe_initpnp (void)
+{
+ int i;
+ for (i = 0; i < AWE_NUM_CHIPS; i++) {
+ pnp_awe[i].id.type = PNP_HDL_ISA;
+ pnp_awe[i].id.t.isa.id = pnp_ids[i];
+ pnp_awe[i].id.next = NULL;
+ pnp_awe[i].name = "Soundblaster AWE32/AWE64 PnP";
+ pnp_awe[i].event = awe_pnp_event;
+ pnp_register_driver(&pnp_awe[i], 1);
+ }
+ return 0;
+}
+
+static void awe_unload_pnp (void)
+{
+ int i;
+ for (i = 0; i < AWE_NUM_CHIPS; i++)
+ pnp_unregister_driver(&pnp_awe[i]);
+}
+#endif /* PnP support */
/*----------------------------------------------------------------
- * old type interface
+ * device / lowlevel (module) interface
*----------------------------------------------------------------*/
-#ifdef AWE_OBSOLETE_VOXWARE
+#ifdef AWE_OBSOLETEL_VOXWARE
-#ifdef __FreeBSD__
-long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
-#else
+/* old type interface */
int attach_awe_obsolete(int mem_start, struct address_info *hw_config)
-#endif
{
my_malloc_init(mem_start);
- if (! attach_awe())
+ if (! _attach_awe())
return 0;
return my_malloc_memptr();
}
@@ -654,8 +773,92 @@ int probe_awe_obsolete(struct address_info *hw_config)
/*return awe_detect();*/
}
+#else /* !obsolete */
+
+/* new type interface */
+int attach_awe(void)
+{
+#ifdef CONFIG_PNP_DRV
+ if (pnp) {
+ awe_initpnp();
+ if (awe_pnp_ok)
+ return 0;
+ }
+#endif /* pnp */
+ _attach_awe();
+ return 0;
+}
+
+void unload_awe(void)
+{
+#ifdef CONFIG_PNP_DRV
+ if (pnp)
+ awe_unload_pnp();
+#endif /* pnp */
+ _unload_awe();
+}
+
+/* module interface */
+
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+int init_module(void)
+{
+ return attach_awe();
+}
+
+void cleanup_module(void)
+{
+ unload_awe();
+}
+
+#ifdef MODULE_PARM
+MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
+MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
+MODULE_SUPPORTED_DEVICE("sound");
#endif
+#endif /* module */
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+#endif /* linux */
+
+
+/*================================================================
+ * FreeBSD interface
+ *================================================================*/
+
+#ifdef __FreeBSD__
+
+#ifdef AWE_OBSOLETE_VOXWARE
+long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
+{
+ _attach_awe();
+ return 0;
+}
+
+int probe_awe_obsolete(struct address_info *hw_config)
+{
+ return 1;
+}
+
+#else /* !obsolete */
+
+/* new type interface */
+void attach_awe(struct address_info *hw_config)
+{
+ _attach_awe();
+}
+
+int probe_awe(struct address_info *hw_config)
+{
+ return 1;
+}
+
+#endif /* obsolete */
+
+#endif /* FreeBSD */
+
/*================================================================
* clear sample tables
@@ -683,26 +886,44 @@ awe_reset_samples(void)
*================================================================*/
/* select a given AWE32 pointer */
+static int awe_ports[5];
+static int port_setuped = FALSE;
static int awe_cur_cmd = -1;
#define awe_set_cmd(cmd) \
-if (awe_cur_cmd != cmd) { OUTW(cmd, awe_base + 0x802); awe_cur_cmd = cmd; }
-#define awe_port(port) (awe_base - 0x620 + port)
+if (awe_cur_cmd != cmd) { OUTW(cmd, awe_ports[Pointer]); awe_cur_cmd = cmd; }
+
+/* store values to i/o port array */
+static void setup_ports(int port1, int port2, int port3)
+{
+ awe_ports[0] = port1;
+ if (port2 == 0)
+ port2 = port1 + 0x400;
+ awe_ports[1] = port2;
+ awe_ports[2] = port2 + 2;
+ if (port3 == 0)
+ port3 = port1 + 0x800;
+ awe_ports[3] = port3;
+ awe_ports[4] = port3 + 2;
+
+ port_setuped = TRUE;
+}
/* write 16bit data */
INLINE static void
awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
{
awe_set_cmd(cmd);
- OUTW(data, awe_port(port));
+ OUTW(data, awe_ports[port]);
}
/* write 32bit data */
INLINE static void
awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data)
{
+ unsigned short addr = awe_ports[port];
awe_set_cmd(cmd);
- OUTW(data, awe_port(port)); /* write lower 16 bits */
- OUTW(data >> 16, awe_port(port)+2); /* write higher 16 bits */
+ OUTW(data, addr); /* write lower 16 bits */
+ OUTW(data >> 16, addr + 2); /* write higher 16 bits */
}
/* read 16bit data */
@@ -711,7 +932,7 @@ awe_peek(unsigned short cmd, unsigned short port)
{
unsigned short k;
awe_set_cmd(cmd);
- k = inw(awe_port(port));
+ k = inw(awe_ports[port]);
return k;
}
@@ -720,19 +941,21 @@ INLINE static unsigned int
awe_peek_dw(unsigned short cmd, unsigned short port)
{
unsigned int k1, k2;
+ unsigned short addr = awe_ports[port];
awe_set_cmd(cmd);
- k1 = inw(awe_port(port));
- k2 = inw(awe_port(port)+2);
+ k1 = inw(addr);
+ k2 = inw(addr + 2);
k1 |= k2 << 16;
return k1;
}
/* wait delay number of AWE32 44100Hz clocks */
+#ifdef WAIT_BY_LOOP /* wait by loop -- that's not good.. */
static void
awe_wait(unsigned short delay)
{
unsigned short clock, target;
- unsigned short port = awe_port(AWE_WC_Port);
+ unsigned short port = awe_ports[AWE_WC_Port];
int counter;
/* sample counter */
@@ -749,6 +972,28 @@ awe_wait(unsigned short delay)
if (counter > 65536)
break;
}
+#else
+
+static struct wait_queue *awe_sleeper = NULL;
+static void awe_wakeup(unsigned long dummy)
+{
+ wake_up(&awe_sleeper);
+}
+
+static struct timer_list awe_timer =
+{NULL, NULL, 0, 0, awe_wakeup};
+
+static void awe_wait(unsigned short delay)
+{
+ unsigned long flags;
+ awe_timer.expires = jiffies + (HZ * (unsigned long)delay + 44099) / 44100;
+ add_timer(&awe_timer);
+ save_flags (flags);
+ cli();
+ sleep_on(&awe_sleeper);
+ restore_flags(flags);
+}
+#endif /* wait by loop */
/* write a word data */
INLINE static void
@@ -758,38 +1003,41 @@ awe_write_dram(unsigned short c)
}
-#ifndef AWE_OBSOLETE_VOXWARE
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
/*================================================================
* port check / request
- * 0x620-622, 0xA20-A22, 0xE20-E22
+ * 0x620-623, 0xA20-A23, 0xE20-E23
*================================================================*/
static int
awe_check_port(void)
{
- return (check_region(awe_port(Data0), 4) ||
- check_region(awe_port(Data1), 4) ||
- check_region(awe_port(Data3), 4));
+ if (! port_setuped) return 0;
+ return (check_region(awe_ports[0], 4) ||
+ check_region(awe_ports[1], 4) ||
+ check_region(awe_ports[3], 4));
}
static void
awe_request_region(void)
{
- request_region(awe_port(Data0), 4, "sound driver (AWE32)");
- request_region(awe_port(Data1), 4, "sound driver (AWE32)");
- request_region(awe_port(Data3), 4, "sound driver (AWE32)");
+ if (! port_setuped) return;
+ request_region(awe_ports[0], 4, "sound driver (AWE32)");
+ request_region(awe_ports[1], 4, "sound driver (AWE32)");
+ request_region(awe_ports[3], 4, "sound driver (AWE32)");
}
static void
awe_release_region(void)
{
- release_region(awe_port(Data0), 4);
- release_region(awe_port(Data1), 4);
- release_region(awe_port(Data3), 4);
+ if (! port_setuped) return;
+ release_region(awe_ports[0], 4);
+ release_region(awe_ports[1], 4);
+ release_region(awe_ports[3], 4);
}
-#endif /* !AWE_OBSOLETE_VOXWARE */
+#endif /* linux && !AWE_OBSOLETE_VOXWARE */
/*================================================================
@@ -817,7 +1065,7 @@ awe_initialize(void)
awe_init_array();
/* check DRAM memory size */
- awe_mem_size = awe_check_dram();
+ awe_check_dram();
/* initialize the FM section of the AWE32 */
awe_init_fm();
@@ -828,8 +1076,15 @@ awe_initialize(void)
/* enable audio */
awe_poke(AWE_HWCF3, 0x0004);
+ /* set default values */
+ awe_init_ctrl_parms(TRUE);
+
/* set equalizer */
- awe_equalizer(5, 9);
+ awe_update_equalizer();
+
+ /* set reverb & chorus modes */
+ awe_update_reverb_mode();
+ awe_update_chorus_mode();
}
@@ -1004,34 +1259,28 @@ calc_rate_offset(int Hz)
/* attack & decay/release time table (msec) */
static short attack_time_tbl[128] = {
-32767, 11878, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742,
- 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371,
- 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188,
- 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94,
- 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47,
- 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23,
- 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11,
- 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 0,
+32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
+707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
+361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
+180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
+90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
+45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
+22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
+11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
};
static short decay_time_tbl[128] = {
-32767, 32766, 4589, 4400, 4219, 4045, 3879, 3719, 3566, 3419, 3279, 3144, 3014, 2890, 2771, 2657,
- 2548, 2443, 2343, 2246, 2154, 2065, 1980, 1899, 1820, 1746, 1674, 1605, 1539, 1475, 1415, 1356,
- 1301, 1247, 1196, 1146, 1099, 1054, 1011, 969, 929, 891, 854, 819, 785, 753, 722, 692,
- 664, 636, 610, 585, 561, 538, 516, 494, 474, 455, 436, 418, 401, 384, 368, 353,
- 339, 325, 311, 298, 286, 274, 263, 252, 242, 232, 222, 213, 204, 196, 188, 180,
- 173, 166, 159, 152, 146, 140, 134, 129, 123, 118, 113, 109, 104, 100, 96, 92,
- 88, 84, 81, 77, 74, 71, 68, 65, 63, 60, 58, 55, 53, 51, 49, 47,
- 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 26, 25, 24,
+32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
+2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
+1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
+691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
+345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
+172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
+86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
+43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
};
-/*
-static int
-calc_parm_delay(int msec)
-{
- return (0x8000 - msec * 1000 / 725);
-}
-*/
+#define calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725);
/* delay time = 0x8000 - msec/92 */
static int
@@ -1095,6 +1344,7 @@ calc_parm_search(int msec, short *table)
#define PARM_BYTE 0
#define PARM_WORD 1
+#define PARM_SIGN 2
static struct PARM_DEFS {
int type; /* byte or word */
@@ -1119,13 +1369,13 @@ static struct PARM_DEFS {
{PARM_WORD, 0, 0x8000, NULL}, /* lfo1 delay */
{PARM_BYTE, 0, 0xff, awe_fx_tremfrq}, /* lfo1 freq */
- {PARM_BYTE, 0, 0x7f, awe_fx_tremfrq}, /* lfo1 volume (positive only)*/
- {PARM_BYTE, 0, 0x7f, awe_fx_fmmod}, /* lfo1 pitch (positive only)*/
- {PARM_BYTE, 0, 0xff, awe_fx_fmmod}, /* lfo1 cutoff (positive only)*/
+ {PARM_SIGN, -128, 127, awe_fx_tremfrq}, /* lfo1 volume */
+ {PARM_SIGN, -128, 127, awe_fx_fmmod}, /* lfo1 pitch */
+ {PARM_BYTE, 0, 0xff, awe_fx_fmmod}, /* lfo1 cutoff */
{PARM_WORD, 0, 0x8000, NULL}, /* lfo2 delay */
{PARM_BYTE, 0, 0xff, awe_fx_fm2frq2}, /* lfo2 freq */
- {PARM_BYTE, 0, 0x7f, awe_fx_fm2frq2}, /* lfo2 pitch (positive only)*/
+ {PARM_SIGN, -128, 127, awe_fx_fm2frq2}, /* lfo2 pitch */
{PARM_WORD, 0, 0xffff, awe_set_voice_pitch}, /* initial pitch */
{PARM_BYTE, 0, 0xff, NULL}, /* chorus */
@@ -1152,8 +1402,16 @@ FX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value)
effect = lay->val[type];
if (!on && (on = FX_ON(rec, type)) != 0)
effect = rec->val[type];
- if (on == FX_FLAG_ADD)
- effect += (int)value;
+ if (on == FX_FLAG_ADD) {
+ if (parm_defs[type].type == PARM_SIGN) {
+ if (value > 0x7f)
+ effect += (int)value - 0x100;
+ else
+ effect += (int)value;
+ } else {
+ effect += (int)value;
+ }
+ }
if (on) {
if (effect < parm_defs[type].low)
effect = parm_defs[type].low;
@@ -1221,12 +1479,20 @@ FX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode)
* turn on/off sample
*================================================================*/
+/* table for volume target calculation */
+static unsigned short voltarget[16] = {
+ 0xEAC0, 0XE0C8, 0XD740, 0XCE20, 0XC560, 0XBD08, 0XB500, 0XAD58,
+ 0XA5F8, 0X9EF0, 0X9830, 0X91C0, 0X8B90, 0X85A8, 0X8000, 0X7A90
+};
+
static void
awe_note_on(int voice)
{
unsigned int temp;
int addr;
+ int vtarget, ftarget, ptarget, pitch;
awe_voice_info *vp;
+ awe_voice_parm_block *parm;
FX_Rec *fx = &voices[voice].cinfo->fx;
FX_Rec *fx_lay = NULL;
if (voices[voice].layer < MAX_LAYERS)
@@ -1236,32 +1502,73 @@ awe_note_on(int voice)
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
+ parm = (awe_voice_parm_block*)&vp->parm;
+
/* channel to be silent and idle */
awe_poke(AWE_DCYSUSV(voice), 0x0080);
- awe_poke(AWE_VTFT(voice), 0);
- awe_poke(AWE_CVCF(voice), 0);
+ awe_poke(AWE_VTFT(voice), 0x0000FFFF);
+ awe_poke(AWE_CVCF(voice), 0x0000FFFF);
awe_poke(AWE_PTRX(voice), 0);
awe_poke(AWE_CPF(voice), 0);
+ /* set pitch offset */
+ awe_set_pitch(voice, TRUE);
+
/* modulation & volume envelope */
- awe_poke(AWE_ENVVAL(voice),
- FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, vp->parm.moddelay));
- awe_poke(AWE_ATKHLD(voice),
- FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
- vp->parm.modatkhld));
+ if (parm->modatk >= 0x80 && parm->moddelay >= 0x8000) {
+ awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+ pitch = (parm->env1pit<<4) + voices[voice].apitch;
+ if (pitch > 0xffff) pitch = 0xffff;
+ /* calculate filter target */
+ ftarget = parm->cutoff + parm->env1fc;
+ limitvalue(ftarget, 0, 255);
+ ftarget <<= 8;
+ } else {
+ awe_poke(AWE_ENVVAL(voice),
+ FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, parm->moddelay));
+ ftarget = parm->cutoff;
+ ftarget <<= 8;
+ pitch = voices[voice].apitch;
+ }
+
+ /* calcualte pitch target */
+ if (pitch != 0xffff) {
+ ptarget = 1 << (pitch >> 12);
+ if (pitch & 0x800) ptarget += (ptarget*0x102e)/0x2710;
+ if (pitch & 0x400) ptarget += (ptarget*0x764)/0x2710;
+ if (pitch & 0x200) ptarget += (ptarget*0x389)/0x2710;
+ ptarget += (ptarget>>1);
+ if (ptarget > 0xffff) ptarget = 0xffff;
+
+ } else ptarget = 0xffff;
+ if (parm->modatk >= 0x80)
+ awe_poke(AWE_ATKHLD(voice),
+ FX_BYTE(fx, fx_lay, AWE_FX_ENV1_HOLD, parm->modhld) << 8 | 0x7f);
+ else
+ awe_poke(AWE_ATKHLD(voice),
+ FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
+ vp->parm.modatkhld));
awe_poke(AWE_DCYSUS(voice),
FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
vp->parm.moddcysus));
- awe_poke(AWE_ENVVOL(voice),
- FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
- awe_poke(AWE_ATKHLDV(voice),
- FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
+
+ if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
+ awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+ vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
+ } else {
+ awe_poke(AWE_ENVVOL(voice),
+ FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
+ vtarget = 0;
+ }
+ if (parm->volatk >= 0x80)
+ awe_poke(AWE_ATKHLDV(voice),
+ FX_BYTE(fx, fx_lay, AWE_FX_ENV2_HOLD, parm->volhld) << 8 | 0x7f);
+ else
+ awe_poke(AWE_ATKHLDV(voice),
+ FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
vp->parm.volatkhld));
/* decay/sustain parameter for volume envelope must be set at last */
- /* pitch offset */
- awe_set_pitch(voice, TRUE);
-
/* cutoff and volume */
awe_set_volume(voice, TRUE);
@@ -1303,9 +1610,13 @@ awe_note_on(int voice)
awe_poke_dw(AWE_CCCA(voice), temp);
DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr));
+ /* clear unknown registers */
+ awe_poke_dw(AWE_00A0(voice), 0);
+ awe_poke_dw(AWE_0080(voice), 0);
+
/* reset volume */
- awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF);
- awe_poke_dw(AWE_CVCF(voice), 0x0000FFFF);
+ awe_poke_dw(AWE_VTFT(voice), (vtarget<<16)|ftarget);
+ awe_poke_dw(AWE_CVCF(voice), (vtarget<<16)|ftarget);
/* turn on envelope */
awe_poke(AWE_DCYSUSV(voice),
@@ -1313,9 +1624,9 @@ awe_note_on(int voice)
vp->parm.voldcysus));
/* set reverb */
temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb);
- temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8);
+ temp = (temp << 8) | (ptarget << 16) | voices[voice].aaux;
awe_poke_dw(AWE_PTRX(voice), temp);
- awe_poke_dw(AWE_CPF(voice), 0x40000000);
+ awe_poke_dw(AWE_CPF(voice), ptarget << 16);
voices[voice].state = AWE_ST_ON;
@@ -1421,7 +1732,8 @@ awe_set_volume(int voice, int forced)
if ((vp = voices[voice].sample) == NULL || vp->index < 0)
return;
- tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF, vp->parm.cutoff);
+ tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF,
+ (unsigned char)voices[voice].acutoff);
tmp2 = (tmp2 << 8);
tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN,
(unsigned char)voices[voice].avol);
@@ -1463,22 +1775,22 @@ awe_set_pan(int voice, int forced)
if (vp->pan >= 0) /* 0-127 */
pos = (int)vp->pan * 2 - 128;
pos += voices[voice].cinfo->panning; /* -128 - 127 */
- pos = 127 - pos;
- if (pos < 0)
- temp = 0;
- else if (pos > 255)
- temp = 255;
- else
- temp = pos;
+ temp = 127 - pos;
+ }
+ limitvalue(temp, 0, 255);
+ if (ctrls[AWE_MD_PAN_EXCHANGE]) {
+ temp = 255 - temp;
}
if (forced || temp != voices[voice].apan) {
+ voices[voice].apan = temp;
addr = vp->loopstart - 1;
addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START,
AWE_FX_COARSE_LOOP_START, vp->mode);
temp = (temp<<24) | (unsigned int)addr;
awe_poke_dw(AWE_PSST(voice), temp);
- voices[voice].apan = temp;
DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr));
+ if (temp == 0) voices[voice].aaux = 0xff;
+ else voices[voice].aaux = (-temp)&0xff;
}
}
@@ -1674,6 +1986,55 @@ static int vol_table[128] = {
2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
};
+/* tables for volume->attenuation calculation */
+static unsigned char voltab1[128] = {
+ 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+ 0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
+ 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
+ 0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
+ 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
+ 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
+ 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
+ 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char voltab2[128] = {
+ 0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
+ 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
+ 0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
+ 0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
+ 0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
+ 0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
+ 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
+ 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char expressiontab[128] = {
+ 0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
+ 0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
+ 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
+ 0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
+ 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
+ 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
+ 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
+ 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
+ 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
+ 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+ 0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
+ 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
static void
awe_calc_volume(int voice)
{
@@ -1693,22 +2054,69 @@ awe_calc_volume(int voice)
return;
}
- /* 0 - 127 */
- vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127);
- vol = vol * ap->amplitude / 127;
+ if (ctrls[AWE_MD_NEW_VOLUME_CALC]) {
+ int main_vol = cp->main_vol * ap->amplitude / 127;
+ limitvalue(vp->velocity, 0, 127);
+ limitvalue(main_vol, 0, 127);
+ limitvalue(cp->expression_vol, 0, 127);
+
+ vol = voltab1[main_vol] + voltab2[vp->velocity];
+ vol = (vol * 8) / 3;
+ vol += ap->attenuation;
+ if (cp->expression_vol < 127)
+ vol += ((0x100 - vol) * expressiontab[cp->expression_vol])/128;
+ vol += atten_offset;
+ if (atten_relative)
+ vol += ctrls[AWE_MD_ZERO_ATTEN];
+ limitvalue(vol, 0, 255);
+ vp->avol = vol;
+
+ } else {
+ /* 0 - 127 */
+ vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127);
+ vol = vol * ap->amplitude / 127;
- if (vol < 0) vol = 0;
- if (vol > 127) vol = 127;
+ if (vol < 0) vol = 0;
+ if (vol > 127) vol = 127;
- /* calc to attenuation */
- vol = vol_table[vol];
- vol = vol + (int)ap->attenuation + init_atten;
- if (vol > 255) vol = 255;
+ /* calc to attenuation */
+ vol = vol_table[vol];
+ vol += (int)ap->attenuation;
+ vol += atten_offset;
+ if (atten_relative)
+ vol += ctrls[AWE_MD_ZERO_ATTEN];
+ if (vol > 255) vol = 255;
- vp->avol = vol;
+ vp->avol = vol;
+ }
+ if (cp->bank != AWE_DRUM_BANK && ((awe_voice_parm_block*)(&ap->parm))->volatk < 0x7d) {
+ int atten;
+ if (vp->velocity < 70) atten = 70;
+ else atten = vp->velocity;
+ vp->acutoff = (atten * ap->parm.cutoff + 0xa0) >> 7;
+ } else {
+ vp->acutoff = ap->parm.cutoff;
+ }
DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));
}
+/* change master volume */
+static void
+awe_change_master_volume(short val)
+{
+ limitvalue(val, 0, 127);
+ atten_offset = vol_table[val];
+ atten_relative = TRUE;
+ awe_update_volume();
+}
+
+/* update volumes of all available channels */
+static void awe_update_volume(void)
+{
+ int i;
+ for (i = 0; i < awe_max_voices; i++)
+ awe_set_voice_vol(i, TRUE);
+}
/* set sostenuto on */
static void awe_sostenuto_on(int voice, int forced)
@@ -1785,7 +2193,7 @@ awe_voice_init(int voice, int init_all)
/* clear effects */
static void awe_fx_init(int ch)
{
- if (SINGLE_LAYER_MODE() && !misc_modes[AWE_MD_KEEP_EFFECT]) {
+ if (SINGLE_LAYER_MODE() && !ctrls[AWE_MD_KEEP_EFFECT]) {
BZERO(&channels[ch].fx, sizeof(channels[ch].fx));
BZERO(&channels[ch].fx_layer, sizeof(&channels[ch].fx_layer));
}
@@ -1801,11 +2209,11 @@ static void awe_channel_init(int ch, int init_all)
cp->bender_range = 200; /* sense * 100 */
cp->main_vol = 127;
if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) {
- cp->instr = misc_modes[AWE_MD_DEF_DRUM];
+ cp->instr = ctrls[AWE_MD_DEF_DRUM];
cp->bank = AWE_DRUM_BANK;
} else {
- cp->instr = misc_modes[AWE_MD_DEF_PRESET];
- cp->bank = misc_modes[AWE_MD_DEF_BANK];
+ cp->instr = ctrls[AWE_MD_DEF_PRESET];
+ cp->bank = ctrls[AWE_MD_DEF_BANK];
}
cp->vrec = -1;
cp->def_vrec = -1;
@@ -1816,7 +2224,7 @@ static void awe_channel_init(int ch, int init_all)
cp->chan_press = 0;
cp->sustained = 0;
- if (! misc_modes[AWE_MD_KEEP_EFFECT]) {
+ if (! ctrls[AWE_MD_KEEP_EFFECT]) {
BZERO(&cp->fx, sizeof(cp->fx));
BZERO(&cp->fx_layer, sizeof(cp->fx_layer));
}
@@ -1861,8 +2269,9 @@ awe_open(int dev, int mode)
awe_busy = TRUE;
/* set default mode */
- awe_init_misc_modes(FALSE);
- init_atten = misc_modes[AWE_MD_ZERO_ATTEN];
+ awe_init_ctrl_parms(FALSE);
+ atten_relative = TRUE;
+ atten_offset = 0;
drum_flags = DEFAULT_DRUM_FLAGS;
playing_mode = AWE_PLAY_INDIRECT;
@@ -1889,12 +2298,12 @@ awe_close(int dev)
/* set miscellaneous mode parameters
*/
static void
-awe_init_misc_modes(int init_all)
+awe_init_ctrl_parms(int init_all)
{
int i;
for (i = 0; i < AWE_MD_END; i++) {
- if (init_all || misc_modes_default[i].init_each_time)
- misc_modes[i] = misc_modes_default[i].value;
+ if (init_all || ctrl_parms[i].init_each_time)
+ ctrls[i] = ctrl_parms[i].value;
}
}
@@ -2078,14 +2487,16 @@ awe_start_note(int dev, int voice, int note, int velocity)
}
/* if the same note still playing, stop it */
- for (i = 0; i < awe_max_voices; i++)
- if (voices[i].key == key) {
- if (voices[i].state == AWE_ST_ON) {
- awe_note_off(i);
- awe_voice_init(i, FALSE);
- } else if (voices[i].state == AWE_ST_STANDBY)
- awe_voice_init(i, TRUE);
- }
+ if (playing_mode != AWE_PLAY_DIRECT || ctrls[AWE_MD_EXCLUSIVE_SOUND]) {
+ for (i = 0; i < awe_max_voices; i++)
+ if (voices[i].key == key) {
+ if (voices[i].state == AWE_ST_ON) {
+ awe_note_off(i);
+ awe_voice_init(i, FALSE);
+ } else if (voices[i].state == AWE_ST_STANDBY)
+ awe_voice_init(i, TRUE);
+ }
+ }
/* allocate voices */
if (playing_mode == AWE_PLAY_DIRECT)
@@ -2114,6 +2525,7 @@ awe_search_instr(int bank, int preset)
{
int i;
+ limitvalue(preset, 0, AWE_MAX_PRESETS-1);
for (i = preset_table[preset]; i >= 0; i = infos[i].next_bank) {
if (infos[i].bank == bank)
return i;
@@ -2158,15 +2570,16 @@ awe_set_instr(int dev, int voice, int instr_no)
cinfo->def_vrec = -1;
cinfo->vrec = awe_search_instr(def_bank, instr_no);
if (def_bank == AWE_DRUM_BANK) /* search default drumset */
- cinfo->def_vrec = awe_search_instr(def_bank, misc_modes[AWE_MD_DEF_DRUM]);
+ cinfo->def_vrec = awe_search_instr(def_bank, ctrls[AWE_MD_DEF_DRUM]);
else /* search default preset */
- cinfo->def_vrec = awe_search_instr(misc_modes[AWE_MD_DEF_BANK], instr_no);
+ cinfo->def_vrec = awe_search_instr(ctrls[AWE_MD_DEF_BANK], instr_no);
if (cinfo->vrec < 0 && cinfo->def_vrec < 0) {
DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
}
cinfo->instr = instr_no;
+ DEBUG(2,printk("AWE32: [program(%d) %d/%d]\n", voice, instr_no, def_bank));
return 0;
}
@@ -2296,7 +2709,7 @@ awe_hw_gus_control(int dev, int cmd, unsigned char *event)
}
}
-#endif
+#endif /* gus_compat */
/* AWE32 specific controls */
@@ -2306,8 +2719,6 @@ awe_hw_awe_control(int dev, int cmd, unsigned char *event)
int voice;
unsigned short p1;
short p2;
- awe_chan_info *cinfo;
- FX_Rec *fx;
int i;
voice = event[3];
@@ -2322,19 +2733,20 @@ awe_hw_awe_control(int dev, int cmd, unsigned char *event)
p1 = *(unsigned short *) &event[4];
p2 = *(short *) &event[6];
- cinfo = &channels[voice];
switch (cmd) {
case _AWE_DEBUG_MODE:
- debug_mode = p1;
- printk("AWE32: debug mode = %d\n", debug_mode);
+ ctrls[AWE_MD_DEBUG_MODE] = p1;
+ printk("AWE32: debug mode = %d\n", ctrls[AWE_MD_DEBUG_MODE]);
break;
case _AWE_REVERB_MODE:
- awe_set_reverb_mode(p1);
+ ctrls[AWE_MD_REVERB_MODE] = p1;
+ awe_update_reverb_mode();
break;
case _AWE_CHORUS_MODE:
- awe_set_chorus_mode(p1);
+ ctrls[AWE_MD_CHORUS_MODE] = p1;
+ awe_update_chorus_mode();
break;
case _AWE_REMOVE_LAST_SAMPLES:
@@ -2348,30 +2760,13 @@ awe_hw_awe_control(int dev, int cmd, unsigned char *event)
break;
case _AWE_SEND_EFFECT:
- fx = &cinfo->fx;
- i = FX_FLAG_SET;
+ i = -1;
if (p1 >= 0x100) {
- int layer = (p1 >> 8);
- if (layer >= 0 && layer < MAX_LAYERS)
- fx = &cinfo->fx_layer[layer];
- p1 &= 0xff;
- }
- if (p1 & 0x40) i = FX_FLAG_OFF;
- if (p1 & 0x80) i = FX_FLAG_ADD;
- p1 &= 0x3f;
- if (p1 < AWE_FX_END) {
- DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, p2));
- if (i == FX_FLAG_SET)
- FX_SET(fx, p1, p2);
- else if (i == FX_FLAG_ADD)
- FX_ADD(fx, p1, p2);
- else
- FX_UNSET(fx, p1);
- if (i != FX_FLAG_OFF && parm_defs[p1].realtime) {
- DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice));
- awe_voice_change(voice, parm_defs[p1].realtime);
- }
+ i = (p1 >> 8);
+ if (i < 0 || i >= MAX_LAYERS)
+ break;
}
+ awe_send_effect(voice, i, p1, p2);
break;
case _AWE_RESET_CHANNEL:
@@ -2395,22 +2790,14 @@ awe_hw_awe_control(int dev, int cmd, unsigned char *event)
case _AWE_INITIAL_VOLUME:
DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
- if (p2 == 0) /* absolute value */
- init_atten = (short)p1;
- else /* relative value */
- init_atten = misc_modes[AWE_MD_ZERO_ATTEN] + (short)p1;
- if (init_atten < 0) init_atten = 0;
- for (i = 0; i < awe_max_voices; i++)
- awe_set_voice_vol(i, TRUE);
+ atten_relative = (char)p2;
+ atten_offset = (short)p1;
+ awe_update_volume();
break;
case _AWE_CHN_PRESSURE:
- cinfo->chan_press = p1;
- p1 = p1 * misc_modes[AWE_MD_MOD_SENSE] / 1200;
- FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, p1);
- awe_voice_change(voice, awe_fx_fmmod);
- FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, p1);
- awe_voice_change(voice, awe_fx_fm2frq2);
+ channels[voice].chan_press = p1;
+ awe_modwheel_change(voice, p1);
break;
case _AWE_CHANNEL_MODE:
@@ -2425,13 +2812,18 @@ awe_hw_awe_control(int dev, int cmd, unsigned char *event)
break;
case _AWE_MISC_MODE:
- DEBUG(0,printk("AWE32: misc mode = %d %d\n", p1, p2));
- if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END)
- misc_modes[p1] = p2;
+ DEBUG(0,printk("AWE32: ctrl parms = %d %d\n", p1, p2));
+ if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) {
+ ctrls[p1] = p2;
+ if (ctrl_parms[p1].update)
+ ctrl_parms[p1].update();
+ }
break;
case _AWE_EQUALIZER:
- awe_equalizer((int)p1, (int)p2);
+ ctrls[AWE_MD_BASS_LEVEL] = p1;
+ ctrls[AWE_MD_TREBLE_LEVEL] = p2;
+ awe_update_equalizer();
break;
default:
@@ -2441,6 +2833,60 @@ awe_hw_awe_control(int dev, int cmd, unsigned char *event)
}
+/* change effects */
+static void
+awe_send_effect(int voice, int layer, int type, int val)
+{
+ awe_chan_info *cinfo;
+ FX_Rec *fx;
+ int mode;
+
+ cinfo = &channels[voice];
+ if (layer >= 0 && layer < MAX_LAYERS)
+ fx = &cinfo->fx_layer[layer];
+ else
+ fx = &cinfo->fx;
+
+ if (type & 0x40)
+ mode = FX_FLAG_OFF;
+ else if (type & 0x80)
+ mode = FX_FLAG_ADD;
+ else
+ mode = FX_FLAG_SET;
+ type &= 0x3f;
+
+ if (type >= 0 && type < AWE_FX_END) {
+ DEBUG(2,printk("AWE32: effects (%d) %d %d\n", voice, type, val));
+ if (mode == FX_FLAG_SET)
+ FX_SET(fx, type, val);
+ else if (mode == FX_FLAG_ADD)
+ FX_ADD(fx, type, val);
+ else
+ FX_UNSET(fx, type);
+ if (mode != FX_FLAG_OFF && parm_defs[type].realtime) {
+ DEBUG(2,printk("AWE32: fx_realtime (%d)\n", voice));
+ awe_voice_change(voice, parm_defs[type].realtime);
+ }
+ }
+}
+
+
+/* change modulation wheel; voice is already mapped on multi2 mode */
+static void
+awe_modwheel_change(int voice, int value)
+{
+ int i;
+ awe_chan_info *cinfo;
+
+ cinfo = &channels[voice];
+ i = value * ctrls[AWE_MD_MOD_SENSE] / 1200;
+ FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i);
+ awe_voice_change(voice, awe_fx_fmmod);
+ FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i);
+ awe_voice_change(voice, awe_fx_fm2frq2);
+}
+
+
/* voice pressure change */
static void
awe_aftertouch(int dev, int voice, int pressure)
@@ -2458,7 +2904,7 @@ awe_aftertouch(int dev, int voice, int pressure)
break;
case AWE_PLAY_MULTI2:
note = (voice_alloc->map[voice] & 0xff) - 1;
- awe_start_note(dev, voice, note + 0x80, pressure);
+ awe_key_pressure(dev, voice, note + 0x80, pressure);
break;
}
}
@@ -2468,7 +2914,6 @@ awe_aftertouch(int dev, int voice, int pressure)
static void
awe_controller(int dev, int voice, int ctrl_num, int value)
{
- int i;
awe_chan_info *cinfo;
if (! voice_in_range(voice))
@@ -2486,7 +2931,7 @@ awe_controller(int dev, int voice, int ctrl_num, int value)
case CTL_BANK_SELECT: /* MIDI control #0 */
DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) &&
- !misc_modes[AWE_MD_TOGGLE_DRUM_BANK])
+ !ctrls[AWE_MD_TOGGLE_DRUM_BANK])
break;
cinfo->bank = value;
if (cinfo->bank == AWE_DRUM_BANK)
@@ -2498,11 +2943,7 @@ awe_controller(int dev, int voice, int ctrl_num, int value)
case CTL_MODWHEEL: /* MIDI control #1 */
DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value));
- i = value * misc_modes[AWE_MD_MOD_SENSE] / 1200;
- FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i);
- awe_voice_change(voice, awe_fx_fmmod);
- FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i);
- awe_voice_change(voice, awe_fx_fm2frq2);
+ awe_modwheel_change(voice, value);
break;
case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */
@@ -2533,7 +2974,7 @@ awe_controller(int dev, int voice, int ctrl_num, int value)
DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
/* (0-127) -> signed 8bit */
cinfo->panning = value * 2 - 128;
- if (misc_modes[AWE_MD_REALTIME_PAN])
+ if (ctrls[AWE_MD_REALTIME_PAN])
awe_voice_change(voice, awe_set_pan);
break;
@@ -2557,14 +2998,12 @@ awe_controller(int dev, int voice, int ctrl_num, int value)
FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2);
break;
-#ifdef AWE_ACCEPT_ALL_SOUNDS_CONTROLL
case 120: /* all sounds off */
awe_note_off_all(FALSE);
break;
case 123: /* all notes off */
awe_note_off_all(TRUE);
break;
-#endif
case CTL_SUSTAIN: /* MIDI control #64 */
cinfo->sustained = value;
@@ -2605,7 +3044,7 @@ awe_panning(int dev, int voice, int value)
cinfo = &channels[voice];
cinfo->panning = value;
DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning));
- if (misc_modes[AWE_MD_REALTIME_PAN])
+ if (ctrls[AWE_MD_REALTIME_PAN])
awe_voice_change(voice, awe_set_pan);
}
@@ -2714,6 +3153,12 @@ awe_load_patch(int dev, int format, const char *addr,
case AWE_MAP_PRESET:
rc = awe_load_map(&patch, addr, count);
break;
+ /* case AWE_PROBE_INFO:
+ rc = awe_probe_info(&patch, addr, count);
+ break;*/
+ case AWE_PROBE_DATA:
+ rc = awe_probe_data(&patch, addr, count);
+ break;
case AWE_LOAD_CHORUS_FX:
rc = awe_load_chorus_fx(&patch, addr, count);
break;
@@ -2740,45 +3185,135 @@ awe_create_sf(int type, char *name)
/* terminate sounds */
awe_reset(0);
if (current_sf_id >= max_sfs) {
+#ifndef AWE_DYNAMIC_BUFFER
+ return 1;
+#else
int newsize = max_sfs + AWE_MAX_SF_LISTS;
- sf_list *newlist = my_realloc(sflists, sizeof(sf_list)*max_sfs,
- sizeof(sf_list)*newsize);
+ sf_list *newlist = realloc_block(sflists, sizeof(sf_list)*max_sfs,
+ sizeof(sf_list)*newsize);
if (newlist == NULL)
return 1;
sflists = newlist;
max_sfs = newsize;
+#endif /* dynamic buffer */
}
rec = &sflists[current_sf_id];
rec->sf_id = current_sf_id + 1;
rec->type = type;
if (current_sf_id == 0 || (type & AWE_PAT_LOCKED) != 0)
locked_sf_id = current_sf_id + 1;
- /*
- if (name)
- MEMCPY(rec->name, name, AWE_PATCH_NAME_LEN);
- else
- BZERO(rec->name, AWE_PATCH_NAME_LEN);
- */
rec->num_info = awe_free_info();
rec->num_sample = awe_free_sample();
rec->mem_ptr = awe_free_mem_ptr();
rec->infos = -1;
rec->samples = -1;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ rec->shared = 0;
+ if (name)
+ memcpy(rec->name, name, AWE_PATCH_NAME_LEN);
+ else
+ strcpy(rec->name, "*TEMPORARY*");
+ if (current_sf_id > 0 && name && (type & AWE_PAT_SHARED) != 0) {
+ /* is the current font really a shared font? */
+ if (is_shared_sf(rec->name)) {
+ /* check if the shared font is already installed */
+ int i;
+ for (i = current_sf_id; i > 0; i--) {
+ if (is_identical_name(rec->name, i)) {
+ rec->shared = i;
+ break;
+ }
+ }
+ }
+ }
+#endif /* allow sharing */
+
current_sf_id++;
+
return 0;
}
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+
+/* check if the given name is a valid shared name */
+#define ASC_TO_KEY(c) ((c) - 'A' + 1)
+static int is_shared_sf(unsigned char *name)
+{
+ static unsigned char id_head[6] = {
+ ASC_TO_KEY('A'), ASC_TO_KEY('W'), ASC_TO_KEY('E'),
+ AWE_MAJOR_VERSION,
+ AWE_MINOR_VERSION,
+ AWE_TINY_VERSION,
+ };
+ if (MEMCMP(name, id_head, 6) == 0)
+ return TRUE;
+ return FALSE;
+}
+
+/* check if the given name matches to the existing list */
+static int is_identical_name(unsigned char *name, int sf)
+{
+ char *id = sflists[sf-1].name;
+ if (is_shared_sf(id) && MEMCMP(id, name, AWE_PATCH_NAME_LEN) == 0)
+ return TRUE;
+ return FALSE;
+}
+
+/* check if the given voice info exists */
+static int info_duplicated(awe_voice_list *rec)
+{
+ int j, sf_id;
+ sf_list *sf;
+
+ /* search for all sharing lists */
+ for (sf_id = rec->v.sf_id; sf_id > 0; sf_id = sf->shared) {
+ sf = &sflists[sf_id - 1];
+ for (j = sf->infos; j >= 0; j = infos[j].next) {
+ awe_voice_list *p = &infos[j];
+ if (p->type == V_ST_NORMAL &&
+ p->bank == rec->bank &&
+ p->instr == rec->instr &&
+ p->v.low == rec->v.low &&
+ p->v.high == rec->v.high &&
+ p->v.sample == rec->v.sample)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+#endif /* AWE_ALLOW_SAMPLE_SHARING */
+
+
/* open patch; create sf list and set opened flag */
static int
awe_open_patch(awe_patch_info *patch, const char *addr, int count)
{
awe_open_parm parm;
+ int shared;
+
COPY_FROM_USER(&parm, addr, AWE_PATCH_INFO_SIZE, sizeof(parm));
- if (awe_create_sf(parm.type, parm.name)) {
- printk("AWE32: can't open: failed to alloc new list\n");
- return RET_ERROR(ENOSPC);
+ shared = FALSE;
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ if (current_sf_id > 0 && (parm.type & AWE_PAT_SHARED) != 0) {
+ /* is the previous font the same font? */
+ if (is_identical_name(parm.name, current_sf_id)) {
+ /* then append to the previous */
+ shared = TRUE;
+ awe_reset(0);
+ if (parm.type & AWE_PAT_LOCKED)
+ locked_sf_id = current_sf_id;
+ }
+ }
+#endif /* allow sharing */
+ if (! shared) {
+ if (awe_create_sf(parm.type, parm.name)) {
+ printk("AWE32: can't open: failed to alloc new list\n");
+ return RET_ERROR(ENOSPC);
+ }
}
patch_opened = TRUE;
return current_sf_id;
@@ -2817,7 +3352,7 @@ awe_close_patch(awe_patch_info *patch, const char *addr, int count)
static int
awe_unload_patch(awe_patch_info *patch, const char *addr, int count)
{
- if (current_sf_id > 0)
+ if (current_sf_id > 0 && current_sf_id > locked_sf_id)
awe_remove_samples(current_sf_id - 1);
return 0;
}
@@ -2829,17 +3364,22 @@ static int alloc_new_info(int nvoices)
awe_voice_list *newlist;
free_info = awe_free_info();
if (free_info + nvoices >= max_infos) {
+#ifndef AWE_DYNAMIC_BUFFER
+ printk("AWE32: can't alloc info table\n");
+ return RET_ERROR(ENOSPC);
+#else
do {
newsize = max_infos + AWE_MAX_INFOS;
} while (free_info + nvoices >= newsize);
- newlist = my_realloc(infos, sizeof(awe_voice_list)*max_infos,
- sizeof(awe_voice_list)*newsize);
+ newlist = realloc_block(infos, sizeof(awe_voice_list)*max_infos,
+ sizeof(awe_voice_list)*newsize);
if (newlist == NULL) {
printk("AWE32: can't alloc info table\n");
return RET_ERROR(ENOSPC);
}
infos = newlist;
max_infos = newsize;
+#endif
}
return 0;
}
@@ -2851,16 +3391,21 @@ static int alloc_new_sample(void)
awe_sample_list *newlist;
free_sample = awe_free_sample();
if (free_sample >= max_samples) {
+#ifndef AWE_DYNAMIC_BUFFER
+ printk("AWE32: can't alloc sample table\n");
+ return RET_ERROR(ENOSPC);
+#else
newsize = max_samples + AWE_MAX_SAMPLES;
- newlist = my_realloc(samples,
- sizeof(awe_sample_list)*max_samples,
- sizeof(awe_sample_list)*newsize);
+ newlist = realloc_block(samples,
+ sizeof(awe_sample_list)*max_samples,
+ sizeof(awe_sample_list)*newsize);
if (newlist == NULL) {
printk("AWE32: can't alloc sample table\n");
return RET_ERROR(ENOSPC);
}
samples = newlist;
max_samples = newsize;
+#endif
}
return 0;
}
@@ -2871,15 +3416,32 @@ awe_load_map(awe_patch_info *patch, const char *addr, int count)
{
awe_voice_map map;
awe_voice_list *rec;
- int free_info;
+ int p, free_info;
+
+ /* get the link info */
+ if (count < sizeof(map)) {
+ printk("AWE32 Error: invalid patch info length\n");
+ return RET_ERROR(EINVAL);
+ }
+ COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
+
+ /* check if the identical mapping already exists */
+ p = awe_search_instr(map.map_bank, map.map_instr);
+ for (; p >= 0; p = infos[p].next_instr) {
+ if (p >= 0 && infos[p].type == V_ST_MAPPED &&
+ infos[p].v.low == map.map_key &&
+ infos[p].v.start == map.src_instr &&
+ infos[p].v.end == map.src_bank &&
+ infos[p].v.fixkey == map.src_key)
+ return 0; /* already present! */
+ }
if (check_patch_opened(AWE_PAT_TYPE_MAP, NULL) < 0)
return RET_ERROR(ENOSPC);
+
if (alloc_new_info(1) < 0)
return RET_ERROR(ENOSPC);
- COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
-
free_info = awe_free_info();
rec = &infos[free_info];
rec->bank = map.map_bank;
@@ -2901,6 +3463,54 @@ awe_load_map(awe_patch_info *patch, const char *addr, int count)
return 0;
}
+#if 0
+/* probe preset in the current list -- nothing to be loaded */
+static int
+awe_probe_info(awe_patch_info *patch, const char *addr, int count)
+{
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ awe_voice_map map;
+ int p;
+
+ if (! patch_opened)
+ return RET_ERROR(EINVAL);
+
+ /* get the link info */
+ if (count < sizeof(map)) {
+ printk("AWE32 Error: invalid patch info length\n");
+ return RET_ERROR(EINVAL);
+ }
+ COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
+
+ /* check if the identical mapping already exists */
+ p = awe_search_instr(map.src_bank, map.src_instr);
+ for (; p >= 0; p = infos[p].next_instr) {
+ if (p >= 0 && infos[p].type == V_ST_NORMAL &&
+ is_identical_id(infos[p].v.sf_id, current_sf_id) &&
+ infos[p].v.low <= map.src_key &&
+ infos[p].v.high >= map.src_key)
+ return 0; /* already present! */
+ }
+#endif /* allow sharing */
+ return RET_ERROR(EINVAL);
+}
+#endif
+
+/* probe sample in the current list -- nothing to be loaded */
+static int
+awe_probe_data(awe_patch_info *patch, const char *addr, int count)
+{
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ if (! patch_opened)
+ return RET_ERROR(EINVAL);
+
+ /* search the specified sample by optarg */
+ if (search_sample_index(current_sf_id, patch->optarg, 0) >= 0)
+ return 0;
+#endif /* allow sharing */
+ return RET_ERROR(EINVAL);
+}
+
/* load voice information data */
static int
awe_load_info(awe_patch_info *patch, const char *addr, int count)
@@ -2965,6 +3575,12 @@ awe_load_info(awe_patch_info *patch, const char *addr, int count)
COPY_FROM_USER(&infos[rec].v, addr, offset, AWE_VOICE_INFO_SIZE);
offset += AWE_VOICE_INFO_SIZE;
infos[rec].v.sf_id = current_sf_id;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ if (sflists[current_sf_id-1].shared) {
+ if (info_duplicated(&infos[rec]))
+ continue;
+ }
+#endif /* allow sharing */
if (infos[rec].v.mode & AWE_MODE_INIT_PARM)
awe_init_voice_parm(&infos[rec].v.parm);
awe_set_sample(&infos[rec].v);
@@ -2975,32 +3591,45 @@ awe_load_info(awe_patch_info *patch, const char *addr, int count)
return 0;
}
+
/* load wave sample data */
static int
awe_load_data(awe_patch_info *patch, const char *addr, int count)
{
int offset, size;
int rc, free_sample;
- awe_sample_info *rec;
+ awe_sample_info tmprec, *rec;
if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0)
return RET_ERROR(ENOSPC);
- if (alloc_new_sample() < 0)
- return RET_ERROR(ENOSPC);
-
- free_sample = awe_free_sample();
- rec = &samples[free_sample].v;
-
size = (count - AWE_SAMPLE_INFO_SIZE) / 2;
offset = AWE_PATCH_INFO_SIZE;
- COPY_FROM_USER(rec, addr, offset, AWE_SAMPLE_INFO_SIZE);
+ COPY_FROM_USER(&tmprec, addr, offset, AWE_SAMPLE_INFO_SIZE);
offset += AWE_SAMPLE_INFO_SIZE;
- if (size != rec->size) {
+ if (size != tmprec.size) {
printk("AWE32: load: sample size differed (%d != %d)\n",
- rec->size, size);
+ tmprec.size, size);
return RET_ERROR(EINVAL);
}
+
+ if (search_sample_index(current_sf_id, tmprec.sample, 0) >= 0) {
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ /* if shared sample, skip this data */
+ if (sflists[current_sf_id-1].type & AWE_PAT_SHARED)
+ return 0;
+#endif /* allow sharing */
+ DEBUG(1,printk("AWE32: sample data %d already present\n", tmprec.sample));
+ return RET_ERROR(EINVAL);
+ }
+
+ if (alloc_new_sample() < 0)
+ return RET_ERROR(ENOSPC);
+
+ free_sample = awe_free_sample();
+ rec = &samples[free_sample].v;
+ *rec = tmprec;
+
if (rec->size > 0)
if ((rc = awe_write_wave_data(addr, offset, rec, -1)) != 0)
return rc;
@@ -3078,7 +3707,7 @@ awe_replace_data(awe_patch_info *patch, const char *addr, int count)
static const char *readbuf_addr;
static int readbuf_offs;
static int readbuf_flags;
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
static unsigned short *readbuf_loop;
static int readbuf_loopstart, readbuf_loopend;
#endif
@@ -3087,7 +3716,7 @@ static int readbuf_loopstart, readbuf_loopend;
static int
readbuf_init(const char *addr, int offset, awe_sample_info *sp)
{
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
readbuf_loop = NULL;
readbuf_loopstart = sp->loopstart;
readbuf_loopend = sp->loopend;
@@ -3121,7 +3750,7 @@ readbuf_word(int pos)
}
if (readbuf_flags & AWE_SAMPLE_UNSIGNED)
c ^= 0x8000; /* unsigned -> signed */
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
/* write on cache for reverse loop */
if (readbuf_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) {
if (pos >= readbuf_loopstart && pos < readbuf_loopend)
@@ -3131,7 +3760,7 @@ readbuf_word(int pos)
return c;
}
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
/* read from cache */
static unsigned short
readbuf_word_cache(int pos)
@@ -3184,7 +3813,7 @@ awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int chann
if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)
truesize += BLANK_LOOP_SIZE;
if (awe_free_mem_ptr() + truesize >= awe_mem_size/2) {
- printk("AWE32 Error: Sample memory full\n");
+ DEBUG(-1,printk("AWE32 Error: Sample memory full\n"));
return RET_ERROR(ENOSPC);
}
@@ -3418,7 +4047,7 @@ awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag)
/* scale_freq, scale_factor, volume, and fractions not implemented */
/* append to the tail of the list */
- infos[free_info].bank = misc_modes[AWE_MD_GUS_BANK];
+ infos[free_info].bank = ctrls[AWE_MD_GUS_BANK];
infos[free_info].instr = patch.instr_no;
infos[free_info].disabled = FALSE;
infos[free_info].type = V_ST_NORMAL;
@@ -3443,7 +4072,7 @@ awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag)
static void add_sf_info(int rec)
{
int sf_id = infos[rec].v.sf_id;
- if (sf_id == 0) return;
+ if (sf_id <= 0) return;
sf_id--;
if (sflists[sf_id].infos < 0)
sflists[sf_id].infos = rec;
@@ -3462,7 +4091,7 @@ static void add_sf_info(int rec)
static void add_sf_sample(int rec)
{
int sf_id = samples[rec].v.sf_id;
- if (sf_id == 0) return;
+ if (sf_id <= 0) return;
sf_id--;
samples[rec].next = sflists[sf_id].samples;
sflists[sf_id].samples = rec;
@@ -3481,12 +4110,12 @@ static void purge_old_list(int rec, int next)
for (cur = next; cur >= 0; cur = infos[cur].next_instr) {
if (infos[cur].v.low == low &&
infos[cur].v.high == high &&
- infos[cur].v.sf_id != infos[rec].v.sf_id)
+ ! is_identical_id(infos[cur].v.sf_id, infos[rec].v.sf_id))
*prevp = infos[cur].next_instr;
prevp = &infos[cur].next_instr;
}
} else {
- if (infos[next].v.sf_id != infos[rec].v.sf_id)
+ if (! is_identical_id(infos[next].v.sf_id, infos[rec].v.sf_id))
infos[rec].next_instr = -1;
}
}
@@ -3495,12 +4124,15 @@ static void purge_old_list(int rec, int next)
static void add_info_list(int rec)
{
int *prevp, cur;
- int instr = infos[rec].instr;
- int bank = infos[rec].bank;
+ int instr;
+ int bank;
if (infos[rec].disabled)
return;
+ instr = infos[rec].instr;
+ bank = infos[rec].bank;
+ limitvalue(instr, 0, AWE_MAX_PRESETS-1);
prevp = &preset_table[instr];
cur = *prevp;
while (cur >= 0) {
@@ -3555,27 +4187,72 @@ static void rebuild_preset_list(void)
}
}
+/* compare the given sf_id pair */
+static int is_identical_id(int id1, int id2)
+{
+ if (id1 == id2)
+ return TRUE;
+ if (id1 <= 0 || id2 <= 0) /* this must not happen.. */
+ return FALSE;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ {
+ /* compare with the sharing id */
+ int i;
+ if (id1 < id2) { /* make sure id1 > id2 */
+ int tmp; tmp = id1; id1 = id2; id2 = tmp;
+ }
+ for (i = sflists[id1-1].shared; i > 0; i = sflists[i-1].shared) {
+ if (i == id2)
+ return TRUE;
+ }
+ }
+#endif /* allow sharing */
+ return FALSE;
+}
+
+/* search the sample index matching with the given sample id */
+static int search_sample_index(int sf, int sample, int level)
+{
+ int i;
+
+ if (sf <= 0 || sf > current_sf_id)
+ return -1; /* this must not happen */
+
+ for (i = sflists[sf-1].samples; i >= 0; i = samples[i].next) {
+ if (samples[i].v.sample == sample)
+ return i;
+ }
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+ if (sflists[sf-1].shared) { /* search recursively */
+ if (level > current_sf_id)
+ return -1; /* strange sharing loop.. quit */
+ return search_sample_index(sflists[sf-1].shared, sample, level + 1);
+ }
+#endif
+ return -1;
+}
+
/* search the specified sample */
static short
awe_set_sample(awe_voice_info *vp)
{
int i;
+
vp->index = -1;
- for (i = sflists[vp->sf_id-1].samples; i >= 0; i = samples[i].next) {
- if (samples[i].v.sample == vp->sample) {
- /* set the actual sample offsets */
- vp->start += samples[i].v.start;
- vp->end += samples[i].v.end;
- vp->loopstart += samples[i].v.loopstart;
- vp->loopend += samples[i].v.loopend;
- /* copy mode flags */
- vp->mode = samples[i].v.mode_flags;
- /* set index */
- vp->index = i;
- return i;
- }
- }
- return -1;
+ if ((i = search_sample_index(vp->sf_id, vp->sample, 0)) < 0)
+ return -1;
+
+ /* set the actual sample offsets */
+ vp->start += samples[i].v.start;
+ vp->end += samples[i].v.end;
+ vp->loopstart += samples[i].v.loopstart;
+ vp->loopend += samples[i].v.loopend;
+ /* copy mode flags */
+ vp->mode = samples[i].v.mode_flags;
+ /* set index */
+ vp->index = i;
+
+ return i;
}
@@ -3682,13 +4359,22 @@ static int
search_best_voice(int condition)
{
int i, time, best;
+ int vtarget = 0xffff, min_vtarget = 0xffff;
+
best = -1;
time = current_alloc_time + 1;
for (i = 0; i < awe_max_voices; i++) {
- if ((voices[i].state & condition) &&
- (best < 0 || voices[i].time < time)) {
+ if (! (voices[i].state & condition))
+ continue;
+#ifdef AWE_CHECK_VTARGET
+ /* get current volume */
+ vtarget = (awe_peek_dw(AWE_VTFT(i)) >> 16) & 0xffff;
+#endif
+ if (best < 0 || vtarget < min_vtarget ||
+ (vtarget == min_vtarget && voices[i].time < time)) {
best = i;
time = voices[i].time;
+ min_vtarget = vtarget;
}
}
/* clear voice */
@@ -3718,8 +4404,7 @@ awe_clear_voice(void)
if ((best = search_best_voice(AWE_ST_SUSTAINED)) >= 0)
return best;
-#ifdef AWE_LOOKUP_MIDI_PRIORITY
- if (MULTI_LAYER_MODE() && misc_modes[AWE_MD_CHN_PRIOR]) {
+ if (MULTI_LAYER_MODE() && ctrls[AWE_MD_CHN_PRIOR]) {
int ch = -1;
int time = current_alloc_time + 1;
int i;
@@ -3735,7 +4420,6 @@ awe_clear_voice(void)
}
}
}
-#endif
if (best < 0)
best = search_best_voice(~AWE_ST_MARK);
@@ -3823,10 +4507,35 @@ awe_setup_voice(int dev, int voice, int chn)
* AWE32 mixer device control
*================================================================*/
+static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg);
+
+static int my_mixerdev = -1;
+
+static struct mixer_operations awe_mixer_operations = {
+#ifndef __FreeBSD__
+ "AWE32",
+#endif
+ "AWE32 Equalizer",
+ awe_mixer_ioctl,
+};
+
+static void attach_mixer(void)
+{
+ if ((my_mixerdev = sound_alloc_mixerdev()) >= 0) {
+ mixer_devs[my_mixerdev] = &awe_mixer_operations;
+ }
+}
+
+static void unload_mixer(void)
+{
+ if (my_mixerdev >= 0)
+ sound_unload_mixerdev(my_mixerdev);
+}
+
static int
awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
- int i, level;
+ int i, level, value;
if (((cmd >> 8) & 0xff) != 'M')
return RET_ERROR(EINVAL);
@@ -3838,38 +4547,43 @@ awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
if (IO_WRITE_CHECK(cmd)) {
switch (cmd & 0xff) {
case SOUND_MIXER_BASS:
- awe_bass_level = level * 12 / 100;
- if (awe_bass_level >= 12)
- awe_bass_level = 11;
- awe_equalizer(awe_bass_level, awe_treble_level);
+ value = level * 12 / 100;
+ if (value >= 12)
+ value = 11;
+ ctrls[AWE_MD_BASS_LEVEL] = value;
+ awe_update_equalizer();
break;
case SOUND_MIXER_TREBLE:
- awe_treble_level = level * 12 / 100;
- if (awe_treble_level >= 12)
- awe_treble_level = 11;
- awe_equalizer(awe_bass_level, awe_treble_level);
+ value = level * 12 / 100;
+ if (value >= 12)
+ value = 11;
+ ctrls[AWE_MD_TREBLE_LEVEL] = value;
+ awe_update_equalizer();
break;
case SOUND_MIXER_VOLUME:
level = level * 127 / 100;
if (level >= 128) level = 127;
- init_atten = vol_table[level];
- for (i = 0; i < awe_max_voices; i++)
- awe_set_voice_vol(i, TRUE);
+ atten_relative = FALSE;
+ atten_offset = vol_table[level];
+ awe_update_volume();
break;
}
}
switch (cmd & 0xff) {
case SOUND_MIXER_BASS:
- level = awe_bass_level * 100 / 24;
+ level = ctrls[AWE_MD_BASS_LEVEL] * 100 / 24;
level = (level << 8) | level;
break;
case SOUND_MIXER_TREBLE:
- level = awe_treble_level * 100 / 24;
+ level = ctrls[AWE_MD_TREBLE_LEVEL] * 100 / 24;
level = (level << 8) | level;
break;
case SOUND_MIXER_VOLUME:
+ value = atten_offset;
+ if (atten_relative)
+ value += ctrls[AWE_MD_ZERO_ATTEN];
for (i = 127; i > 0; i--) {
- if (init_atten <= vol_table[i])
+ if (value <= vol_table[i])
break;
}
level = i * 100 / 127;
@@ -4168,8 +4882,10 @@ awe_open_dram_for_write(int offset, int channels)
for (i = 0; i < AWE_NORMAL_VOICES; i++)
vidx[i] = i;
} else {
- for (i = 0; i < channels; i++)
+ for (i = 0; i < channels; i++) {
vidx[i] = awe_clear_voice();
+ voices[vidx[i]].state = AWE_ST_MARK;
+ }
}
/* use all channels for DMA transfer */
@@ -4201,7 +4917,7 @@ awe_open_dram_for_write(int offset, int channels)
if (awe_peek_dw(AWE_SMALW) & 0x80000000) {
for (i = 0; i < channels; i++) {
awe_poke_dw(AWE_CCCA(vidx[i]), 0);
- voices[i].state = AWE_ST_OFF;
+ voices[vidx[i]].state = AWE_ST_OFF;
}
return RET_ERROR(ENOSPC);
}
@@ -4265,14 +4981,14 @@ awe_close_dram(void)
static int
awe_detect_base(int addr)
{
- awe_base = addr;
+ setup_ports(addr, 0, 0);
if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
return 0;
if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
return 0;
if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
return 0;
- DEBUG(0,printk("AWE32 found at %x\n", awe_base));
+ DEBUG(0,printk("AWE32 found at %x\n", addr));
return 1;
}
@@ -4280,13 +4996,22 @@ static int
awe_detect(void)
{
int base;
- if (awe_base == 0) {
+
+ if (port_setuped) /* already initialized by PnP */
+ return 1;
+
+ if (awe_port) /* use default i/o port value */
+ setup_ports(awe_port, 0, 0);
+ else { /* probe it */
for (base = 0x620; base <= 0x680; base += 0x20)
if (awe_detect_base(base))
return 1;
DEBUG(0,printk("AWE32 not found\n"));
return 0;
}
+ if (memsize >= 0) /* given by config file or module option */
+ awe_mem_size = memsize * 1024; /* convert to Kbytes */
+
return 1;
}
@@ -4300,13 +5025,11 @@ awe_detect(void)
#define UNIQUE_ID2 0x4321
#define UNIQUE_ID3 0xFFFF
-static int
+static void
awe_check_dram(void)
{
- if (awe_mem_size > 0) {
- awe_mem_size *= 1024; /* convert to Kbytes */
- return awe_mem_size;
- }
+ if (awe_mem_size >= 0) /* already initialized */
+ return;
awe_open_dram_for_check();
@@ -4318,7 +5041,7 @@ awe_check_dram(void)
awe_poke(AWE_SMLD, UNIQUE_ID2);
while (awe_mem_size < AWE_MAX_DRAM_SIZE) {
- awe_wait(2);
+ awe_wait(5);
/* read a data on the DRAM start address */
awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET);
awe_peek(AWE_SMLD); /* discard stale data */
@@ -4326,7 +5049,7 @@ awe_check_dram(void)
break;
if (awe_peek(AWE_SMLD) != UNIQUE_ID2)
break;
- awe_mem_size += 32; /* increment 32 Kbytes */
+ awe_mem_size += 512; /* increment 512kbytes */
/* Write a unique data on the test address;
* if the address is out of range, the data is written on
* 0x200000(=AWE_DRAM_OFFSET). Then the two id words are
@@ -4334,7 +5057,7 @@ awe_check_dram(void)
*/
awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L);
awe_poke(AWE_SMLD, UNIQUE_ID3);
- awe_wait(2);
+ awe_wait(5);
/* read a data on the just written DRAM address */
awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + awe_mem_size*512L);
awe_peek(AWE_SMLD); /* discard stale data */
@@ -4347,7 +5070,6 @@ awe_check_dram(void)
/* convert to Kbytes */
awe_mem_size *= 1024;
- return awe_mem_size;
}
@@ -4398,7 +5120,12 @@ awe_set_chorus_mode(int effect)
awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq);
awe_poke_dw(AWE_HWCF6, 0x8000);
awe_poke_dw(AWE_HWCF7, 0x0000);
- chorus_mode = effect;
+}
+
+static void
+awe_update_chorus_mode(void)
+{
+ awe_set_chorus_mode(ctrls[AWE_MD_CHORUS_MODE]);
}
/*----------------------------------------------------------------*/
@@ -4497,7 +5224,12 @@ awe_set_reverb_mode(int effect)
for (i = 0; i < 28; i++)
awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port,
reverb_parm[effect].parms[i]);
- reverb_mode = effect;
+}
+
+static void
+awe_update_reverb_mode(void)
+{
+ awe_set_reverb_mode(ctrls[AWE_MD_REVERB_MODE]);
}
/*================================================================
@@ -4545,8 +5277,6 @@ awe_equalizer(int bass, int treble)
if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
return;
- awe_bass_level = bass;
- awe_treble_level = treble;
awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]);
awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]);
awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]);
@@ -4562,20 +5292,968 @@ awe_equalizer(int bass, int treble)
awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362));
}
+static void awe_update_equalizer(void)
+{
+ awe_equalizer(ctrls[AWE_MD_BASS_LEVEL], ctrls[AWE_MD_TREBLE_LEVEL]);
+}
-#endif /* CONFIG_AWE32_SYNTH */
-#ifdef MODULE
-int init_module(void)
+#ifdef CONFIG_AWE32_MIDIEMU
+
+/*================================================================
+ * Emu8000 MIDI Emulation
+ *================================================================*/
+
+/*================================================================
+ * midi queue record
+ *================================================================*/
+
+/* queue type */
+enum { Q_NONE, Q_VARLEN, Q_READ, Q_SYSEX, };
+
+#define MAX_MIDIBUF 64
+
+/* midi status */
+typedef struct MidiStatus {
+ int queue; /* queue type */
+ int qlen; /* queue length */
+ int read; /* chars read */
+ int status; /* current status */
+ int chan; /* current channel */
+ unsigned char buf[MAX_MIDIBUF];
+} MidiStatus;
+
+/* MIDI mode type */
+enum { MODE_GM, MODE_GS, MODE_XG, };
+
+/* NRPN / CC -> Emu8000 parameter converter */
+typedef struct {
+ int control;
+ int awe_effect;
+ unsigned short (*convert)(int val);
+} ConvTable;
+
+
+/*================================================================
+ * prototypes
+ *================================================================*/
+
+static int awe_midi_open(int dev, int mode, void (*input)(int,unsigned char), void (*output)(int));
+static void awe_midi_close(int dev);
+static int awe_midi_ioctl(int dev, unsigned cmd, caddr_t arg);
+static int awe_midi_outputc(int dev, unsigned char midi_byte);
+
+static void init_midi_status(MidiStatus *st);
+static void clear_rpn(void);
+static void get_midi_char(MidiStatus *st, int c);
+/*static void queue_varlen(MidiStatus *st, int c);*/
+static void special_event(MidiStatus *st, int c);
+static void queue_read(MidiStatus *st, int c);
+static void midi_note_on(MidiStatus *st);
+static void midi_note_off(MidiStatus *st);
+static void midi_key_pressure(MidiStatus *st);
+static void midi_channel_pressure(MidiStatus *st);
+static void midi_pitch_wheel(MidiStatus *st);
+static void midi_program_change(MidiStatus *st);
+static void midi_control_change(MidiStatus *st);
+static void midi_select_bank(MidiStatus *st, int val);
+static void midi_nrpn_event(MidiStatus *st);
+static void midi_rpn_event(MidiStatus *st);
+static void midi_detune(int chan, int coarse, int fine);
+static void midi_system_exclusive(MidiStatus *st);
+static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
+static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
+static int xg_control_change(MidiStatus *st, int cmd, int val);
+
+#define numberof(ary) (sizeof(ary)/sizeof(ary[0]))
+
+
+/*================================================================
+ * OSS Midi device record
+ *================================================================*/
+
+static struct midi_operations awe_midi_operations =
+{
+ {"AWE Midi Emu", 0, 0, SNDCARD_SB},
+ NULL /*&std_midi_synth*/,
+ {0}, /* input_info */
+ awe_midi_open, /*open*/
+ awe_midi_close, /*close*/
+ awe_midi_ioctl, /*ioctl*/
+ awe_midi_outputc, /*outputc*/
+ NULL /*start_read*/,
+ NULL /*end_read*/,
+ NULL, /* kick */
+ NULL, /* command */
+};
+
+static int my_mididev = -1;
+
+static void attach_midiemu(void)
{
- attach_awe();
- SOUND_LOCK;
+ if ((my_mididev = sound_alloc_mididev()) < 0)
+ printk ("Sound: Too many midi devices detected\n");
+ else
+ midi_devs[my_mididev] = &awe_midi_operations;
+}
+
+static void unload_midiemu(void)
+{
+ if (my_mididev >= 0)
+ sound_unload_mididev(my_mididev);
+}
+
+
+/*================================================================
+ * open/close midi device
+ *================================================================*/
+
+static int midi_opened = FALSE;
+
+static int midi_mode;
+static int coarsetune = 0, finetune = 0;
+
+static int xg_mapping = TRUE;
+static int xg_bankmode = 0;
+
+/* effect sensitivity */
+
+#define FX_CUTOFF 0
+#define FX_RESONANCE 1
+#define FX_ATTACK 2
+#define FX_RELEASE 3
+#define FX_VIBRATE 4
+#define FX_VIBDEPTH 5
+#define FX_VIBDELAY 6
+#define FX_NUMS 7
+
+#define DEF_FX_CUTOFF 170
+#define DEF_FX_RESONANCE 6
+#define DEF_FX_ATTACK 50
+#define DEF_FX_RELEASE 50
+#define DEF_FX_VIBRATE 30
+#define DEF_FX_VIBDEPTH 4
+#define DEF_FX_VIBDELAY 1500
+
+/* effect sense: */
+static int gs_sense[] =
+{
+ DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
+ DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
+};
+static int xg_sense[] =
+{
+ DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
+ DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
+};
+
+
+/* current status */
+static MidiStatus curst;
+
+
+static int
+awe_midi_open (int dev, int mode,
+ void (*input)(int,unsigned char),
+ void (*output)(int))
+{
+ if (midi_opened)
+ return -EBUSY;
+
+ midi_opened = TRUE;
+
+ midi_mode = MODE_GM;
+
+ curst.queue = Q_NONE;
+ curst.qlen = 0;
+ curst.read = 0;
+ curst.status = 0;
+ curst.chan = 0;
+ BZERO(curst.buf, sizeof(curst.buf));
+
+ init_midi_status(&curst);
+
return 0;
}
-void cleanup_module(void)
+static void
+awe_midi_close (int dev)
{
- unload_awe();
- SOUND_LOCK_END;
+ midi_opened = FALSE;
+}
+
+
+static int
+awe_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
+{
+ return -EPERM;
+}
+
+static int
+awe_midi_outputc (int dev, unsigned char midi_byte)
+{
+ if (! midi_opened)
+ return 1;
+
+ /* force to change playing mode */
+ playing_mode = AWE_PLAY_MULTI;
+
+ get_midi_char(&curst, midi_byte);
+ return 1;
+}
+
+
+/*================================================================
+ * initialize
+ *================================================================*/
+
+static void init_midi_status(MidiStatus *st)
+{
+ clear_rpn();
+ coarsetune = 0;
+ finetune = 0;
+}
+
+
+/*================================================================
+ * RPN & NRPN
+ *================================================================*/
+
+#define MAX_MIDI_CHANNELS 16
+
+/* RPN & NRPN */
+static unsigned char nrpn[MAX_MIDI_CHANNELS]; /* current event is NRPN? */
+static int msb_bit; /* current event is msb for RPN/NRPN */
+/* RPN & NRPN indeces */
+static unsigned char rpn_msb[MAX_MIDI_CHANNELS], rpn_lsb[MAX_MIDI_CHANNELS];
+/* RPN & NRPN values */
+static int rpn_val[MAX_MIDI_CHANNELS];
+
+static void clear_rpn(void)
+{
+ int i;
+ for (i = 0; i < MAX_MIDI_CHANNELS; i++) {
+ nrpn[i] = 0;
+ rpn_msb[i] = 127;
+ rpn_lsb[i] = 127;
+ rpn_val[i] = 0;
+ }
+ msb_bit = 0;
+}
+
+
+/*================================================================
+ * process midi queue
+ *================================================================*/
+
+/* status event types */
+typedef void (*StatusEvent)(MidiStatus *st);
+static struct StatusEventList {
+ StatusEvent process;
+ int qlen;
+} status_event[8] = {
+ {midi_note_off, 2},
+ {midi_note_on, 2},
+ {midi_key_pressure, 2},
+ {midi_control_change, 2},
+ {midi_program_change, 1},
+ {midi_channel_pressure, 1},
+ {midi_pitch_wheel, 2},
+ {NULL, 0},
+};
+
+
+/* read a char from fifo and process it */
+static void get_midi_char(MidiStatus *st, int c)
+{
+ if (c == 0xfe) {
+ /* ignore active sense */
+ st->queue = Q_NONE;
+ return;
+ }
+
+ switch (st->queue) {
+ /* case Q_VARLEN: queue_varlen(st, c); break;*/
+ case Q_READ:
+ case Q_SYSEX:
+ queue_read(st, c);
+ break;
+ case Q_NONE:
+ st->read = 0;
+ if ((c & 0xf0) == 0xf0) {
+ special_event(st, c);
+ } else if (c & 0x80) { /* status change */
+ st->status = (c >> 4) & 0x07;
+ st->chan = c & 0x0f;
+ st->queue = Q_READ;
+ st->qlen = status_event[st->status].qlen;
+ if (st->qlen == 0)
+ st->queue = Q_NONE;
+ }
+ break;
+ }
+}
+
+/* 0xfx events */
+static void special_event(MidiStatus *st, int c)
+{
+ switch (c) {
+ case 0xf0: /* system exclusive */
+ st->queue = Q_SYSEX;
+ st->qlen = 0;
+ break;
+ case 0xf1: /* MTC quarter frame */
+ case 0xf3: /* song select */
+ st->queue = Q_READ;
+ st->qlen = 1;
+ break;
+ case 0xf2: /* song position */
+ st->queue = Q_READ;
+ st->qlen = 2;
+ break;
+ }
+}
+
+#if 0
+/* read variable length value */
+static void queue_varlen(MidiStatus *st, int c)
+{
+ st->qlen += (c & 0x7f);
+ if (c & 0x80) {
+ st->qlen <<= 7;
+ return;
+ }
+ if (st->qlen <= 0) {
+ st->qlen = 0;
+ st->queue = Q_NONE;
+ }
+ st->queue = Q_READ;
+ st->read = 0;
+}
+#endif
+
+
+/* read a char */
+static void queue_read(MidiStatus *st, int c)
+{
+ if (st->read < MAX_MIDIBUF) {
+ if (st->queue != Q_SYSEX)
+ c &= 0x7f;
+ st->buf[st->read] = (unsigned char)c;
+ }
+ st->read++;
+ if (st->queue == Q_SYSEX && c == 0xf7) {
+ midi_system_exclusive(st);
+ st->queue = Q_NONE;
+ } else if (st->queue == Q_READ && st->read >= st->qlen) {
+ if (status_event[st->status].process)
+ status_event[st->status].process(st);
+ st->queue = Q_NONE;
+ }
+}
+
+
+/*================================================================
+ * status events
+ *================================================================*/
+
+/* note on */
+static void midi_note_on(MidiStatus *st)
+{
+ DEBUG(2,printk("midi: note_on (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
+ if (st->buf[1] == 0)
+ midi_note_off(st);
+ else
+ awe_start_note(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* note off */
+static void midi_note_off(MidiStatus *st)
+{
+ DEBUG(2,printk("midi: note_off (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
+ awe_kill_note(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* key pressure change */
+static void midi_key_pressure(MidiStatus *st)
+{
+ awe_key_pressure(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* channel pressure change */
+static void midi_channel_pressure(MidiStatus *st)
+{
+ channels[st->chan].chan_press = st->buf[0];
+ awe_modwheel_change(st->chan, st->buf[0]);
+}
+
+/* pitch wheel change */
+static void midi_pitch_wheel(MidiStatus *st)
+{
+ int val = (int)st->buf[1] * 128 + st->buf[0];
+ awe_bender(0, st->chan, val);
+}
+
+/* program change */
+static void midi_program_change(MidiStatus *st)
+{
+ int preset;
+ preset = st->buf[0];
+ if (midi_mode == MODE_GS && IS_DRUM_CHANNEL(st->chan) && preset == 127)
+ preset = 0;
+ else if (midi_mode == MODE_XG && xg_mapping && IS_DRUM_CHANNEL(st->chan))
+ preset += 64;
+
+ awe_set_instr(0, st->chan, preset);
}
+
+#define send_effect(chan,type,val) awe_send_effect(chan,-1,type,val)
+#define add_effect(chan,type,val) awe_send_effect(chan,-1,(type)|0x80,val)
+#define unset_effect(chan,type) awe_send_effect(chan,-1,(type)|0x40,0)
+
+/* midi control change */
+static void midi_control_change(MidiStatus *st)
+{
+ int cmd = st->buf[0];
+ int val = st->buf[1];
+
+ DEBUG(2,printk("midi: control (%d) %d %d\n", st->chan, cmd, val));
+ if (midi_mode == MODE_XG) {
+ if (xg_control_change(st, cmd, val))
+ return;
+ }
+
+ /* controls #31 - #64 are LSB of #0 - #31 */
+ msb_bit = 1;
+ if (cmd >= 0x20 && cmd < 0x40) {
+ msb_bit = 0;
+ cmd -= 0x20;
+ }
+
+ switch (cmd) {
+ case CTL_SOFT_PEDAL:
+ if (val == 127)
+ add_effect(st->chan, AWE_FX_CUTOFF, -160);
+ else
+ unset_effect(st->chan, AWE_FX_CUTOFF);
+ break;
+
+ case CTL_BANK_SELECT:
+ midi_select_bank(st, val);
+ break;
+
+ /* set RPN/NRPN parameter */
+ case CTL_REGIST_PARM_NUM_MSB:
+ nrpn[st->chan]=0; rpn_msb[st->chan]=val;
+ break;
+ case CTL_REGIST_PARM_NUM_LSB:
+ nrpn[st->chan]=0; rpn_lsb[st->chan]=val;
+ break;
+ case CTL_NONREG_PARM_NUM_MSB:
+ nrpn[st->chan]=1; rpn_msb[st->chan]=val;
+ break;
+ case CTL_NONREG_PARM_NUM_LSB:
+ nrpn[st->chan]=1; rpn_lsb[st->chan]=val;
+ break;
+
+ /* send RPN/NRPN entry */
+ case CTL_DATA_ENTRY:
+ if (msb_bit)
+ rpn_val[st->chan] = val * 128;
+ else
+ rpn_val[st->chan] |= val;
+ if (nrpn[st->chan])
+ midi_nrpn_event(st);
+ else
+ midi_rpn_event(st);
+ break;
+
+ /* increase/decrease data entry */
+ case CTL_DATA_INCREMENT:
+ rpn_val[st->chan]++;
+ midi_rpn_event(st);
+ break;
+ case CTL_DATA_DECREMENT:
+ rpn_val[st->chan]--;
+ midi_rpn_event(st);
+ break;
+
+ /* default */
+ default:
+ awe_controller(0, st->chan, cmd, val);
+ break;
+ }
+}
+
+/* tone bank change */
+static void midi_select_bank(MidiStatus *st, int val)
+{
+ if (midi_mode == MODE_XG && msb_bit) {
+ xg_bankmode = val;
+ /* XG MSB value; not normal bank selection */
+ switch (val) {
+ case 127: /* remap to drum channel */
+ awe_controller(0, st->chan, CTL_BANK_SELECT, 128);
+ break;
+ default: /* remap to normal channel */
+ awe_controller(0, st->chan, CTL_BANK_SELECT, val);
+ break;
+ }
+ return;
+ } else if (midi_mode == MODE_GS && !msb_bit)
+ /* ignore LSB bank in GS mode (used for mapping) */
+ return;
+
+ /* normal bank controls; accept both MSB and LSB */
+ if (! IS_DRUM_CHANNEL(st->chan)) {
+ if (midi_mode == MODE_XG) {
+ if (xg_bankmode) return;
+ if (val == 64 || val == 126)
+ val = 0;
+ } else if (midi_mode == MODE_GS && val == 127)
+ val = 0;
+ awe_controller(0, st->chan, CTL_BANK_SELECT, val);
+ }
+}
+
+
+/*================================================================
+ * RPN events
+ *================================================================*/
+
+static void midi_rpn_event(MidiStatus *st)
+{
+ int type;
+ type = (rpn_msb[st->chan]<<8) | rpn_lsb[st->chan];
+ switch (type) {
+ case 0x0000: /* Pitch bend sensitivity */
+ /* MSB only / 1 semitone per 128 */
+ if (msb_bit) {
+ channels[st->chan].bender_range =
+ rpn_val[st->chan] * 100 / 128;
+ }
+ break;
+
+ case 0x0001: /* fine tuning: */
+ /* MSB/LSB, 8192=center, 100/8192 cent step */
+ finetune = rpn_val[st->chan] - 8192;
+ midi_detune(st->chan, coarsetune, finetune);
+ break;
+
+ case 0x0002: /* coarse tuning */
+ /* MSB only / 8192=center, 1 semitone per 128 */
+ if (msb_bit) {
+ coarsetune = rpn_val[st->chan] - 8192;
+ midi_detune(st->chan, coarsetune, finetune);
+ }
+ break;
+
+ case 0x7F7F: /* "lock-in" RPN */
+ break;
+ }
+}
+
+
+/* tuning:
+ * coarse = -8192 to 8192 (100 cent per 128)
+ * fine = -8192 to 8192 (max=100cent)
+ */
+static void midi_detune(int chan, int coarse, int fine)
+{
+ /* 4096 = 1200 cents in AWE parameter */
+ int val;
+ val = coarse * 4096 / (12 * 128);
+ val += fine / 24;
+ if (val)
+ send_effect(chan, AWE_FX_INIT_PITCH, val);
+ else
+ unset_effect(chan, AWE_FX_INIT_PITCH);
+}
+
+
+/*================================================================
+ * system exclusive message
+ * GM/GS/XG macros are accepted
+ *================================================================*/
+
+static void midi_system_exclusive(MidiStatus *st)
+{
+ /* GM on */
+ static unsigned char gm_on_macro[] = {
+ 0x7e,0x7f,0x09,0x01,
+ };
+ /* XG on */
+ static unsigned char xg_on_macro[] = {
+ 0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
+ };
+ /* GS prefix
+ * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off
+ * reverb mode: XX=0x01, YY=0x30, ZZ=0-7
+ * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
+ */
+ static unsigned char gs_pfx_macro[] = {
+ 0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
+ };
+
+#if 0
+ /* SC88 system mode set
+ * single module mode: XX=1
+ * double module mode: XX=0
+ */
+ static unsigned char gs_mode_macro[] = {
+ 0x41,0x10,0x42,0x12,0x00,0x00,0x7F,/*ZZ*/
+ };
+ /* SC88 display macro: XX=01:bitmap, 00:text
+ */
+ static unsigned char gs_disp_macro[] = {
+ 0x41,0x10,0x45,0x12,0x10,/*XX,00*/
+ };
#endif
+
+ /* GM on */
+ if (MEMCMP(st->buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
+ if (midi_mode != MODE_GS && midi_mode != MODE_XG)
+ midi_mode = MODE_GM;
+ init_midi_status(st);
+ }
+
+ /* GS macros */
+ else if (MEMCMP(st->buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
+ if (midi_mode != MODE_GS && midi_mode != MODE_XG)
+ midi_mode = MODE_GS;
+
+ if (st->buf[5] == 0x00 && st->buf[6] == 0x7f && st->buf[7] == 0x00) {
+ /* GS reset */
+ init_midi_status(st);
+ }
+
+ else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x15) {
+ /* drum pattern */
+ int p = st->buf[5] & 0x0f;
+ if (p == 0) p = 9;
+ else if (p < 10) p--;
+ if (st->buf[7] == 0)
+ DRUM_CHANNEL_OFF(p);
+ else
+ DRUM_CHANNEL_ON(p);
+
+ } else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x21) {
+ /* program */
+ int p = st->buf[5] & 0x0f;
+ if (p == 0) p = 9;
+ else if (p < 10) p--;
+ if (! IS_DRUM_CHANNEL(p))
+ awe_set_instr(0, p, st->buf[7]);
+
+ } else if (st->buf[5] == 0x01 && st->buf[6] == 0x30) {
+ /* reverb mode */
+ awe_set_reverb_mode(st->buf[7]);
+
+ } else if (st->buf[5] == 0x01 && st->buf[6] == 0x38) {
+ /* chorus mode */
+ awe_set_chorus_mode(st->buf[7]);
+
+ } else if (st->buf[5] == 0x00 && st->buf[6] == 0x04) {
+ /* master volume */
+ awe_change_master_volume(st->buf[7]);
+
+ }
+ }
+
+ /* XG on */
+ else if (MEMCMP(st->buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
+ midi_mode = MODE_XG;
+ xg_mapping = TRUE;
+ xg_bankmode = 0;
+ }
+}
+
+
+/*================================================================
+ * convert NRPN/control values
+ *================================================================*/
+
+static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
+{
+ int i, cval;
+ for (i = 0; i < num_tables; i++) {
+ if (table[i].control == type) {
+ cval = table[i].convert(val);
+ send_effect(st->chan, table[i].awe_effect, cval);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
+{
+ int i, cval;
+ for (i = 0; i < num_tables; i++) {
+ if (table[i].control == type) {
+ cval = table[i].convert(val);
+ add_effect(st->chan, table[i].awe_effect|0x80, cval);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/*----------------------------------------------------------------
+ * AWE32 NRPN effects
+ *----------------------------------------------------------------*/
+
+static unsigned short fx_delay(int val);
+static unsigned short fx_attack(int val);
+static unsigned short fx_hold(int val);
+static unsigned short fx_decay(int val);
+static unsigned short fx_the_value(int val);
+static unsigned short fx_twice_value(int val);
+static unsigned short fx_conv_pitch(int val);
+static unsigned short fx_conv_Q(int val);
+
+/* function for each NRPN */ /* [range] units */
+#define fx_env1_delay fx_delay /* [0,5900] 4msec */
+#define fx_env1_attack fx_attack /* [0,5940] 1msec */
+#define fx_env1_hold fx_hold /* [0,8191] 1msec */
+#define fx_env1_decay fx_decay /* [0,5940] 4msec */
+#define fx_env1_release fx_decay /* [0,5940] 4msec */
+#define fx_env1_sustain fx_the_value /* [0,127] 0.75dB */
+#define fx_env1_pitch fx_the_value /* [-127,127] 9.375cents */
+#define fx_env1_cutoff fx_the_value /* [-127,127] 56.25cents */
+
+#define fx_env2_delay fx_delay /* [0,5900] 4msec */
+#define fx_env2_attack fx_attack /* [0,5940] 1msec */
+#define fx_env2_hold fx_hold /* [0,8191] 1msec */
+#define fx_env2_decay fx_decay /* [0,5940] 4msec */
+#define fx_env2_release fx_decay /* [0,5940] 4msec */
+#define fx_env2_sustain fx_the_value /* [0,127] 0.75dB */
+
+#define fx_lfo1_delay fx_delay /* [0,5900] 4msec */
+#define fx_lfo1_freq fx_twice_value /* [0,127] 84mHz */
+#define fx_lfo1_volume fx_twice_value /* [0,127] 0.1875dB */
+#define fx_lfo1_pitch fx_the_value /* [-127,127] 9.375cents */
+#define fx_lfo1_cutoff fx_twice_value /* [-64,63] 56.25cents */
+
+#define fx_lfo2_delay fx_delay /* [0,5900] 4msec */
+#define fx_lfo2_freq fx_twice_value /* [0,127] 84mHz */
+#define fx_lfo2_pitch fx_the_value /* [-127,127] 9.375cents */
+
+#define fx_init_pitch fx_conv_pitch /* [-8192,8192] cents */
+#define fx_chorus fx_the_value /* [0,255] -- */
+#define fx_reverb fx_the_value /* [0,255] -- */
+#define fx_cutoff fx_twice_value /* [0,127] 62Hz */
+#define fx_filterQ fx_conv_Q /* [0,127] -- */
+
+static unsigned short fx_delay(int val)
+{
+ return (unsigned short)calc_parm_delay(val);
+}
+
+static unsigned short fx_attack(int val)
+{
+ return (unsigned short)calc_parm_attack(val);
+}
+
+static unsigned short fx_hold(int val)
+{
+ return (unsigned short)calc_parm_hold(val);
+}
+
+static unsigned short fx_decay(int val)
+{
+ return (unsigned short)calc_parm_decay(val);
+}
+
+static unsigned short fx_the_value(int val)
+{
+ return (unsigned short)(val & 0xff);
+}
+
+static unsigned short fx_twice_value(int val)
+{
+ return (unsigned short)((val * 2) & 0xff);
+}
+
+static unsigned short fx_conv_pitch(int val)
+{
+ return (short)(val * 4096 / 1200);
+}
+
+static unsigned short fx_conv_Q(int val)
+{
+ return (unsigned short)((val / 8) & 0xff);
+}
+
+
+static ConvTable awe_effects[] =
+{
+ { 0, AWE_FX_LFO1_DELAY, fx_lfo1_delay},
+ { 1, AWE_FX_LFO1_FREQ, fx_lfo1_freq},
+ { 2, AWE_FX_LFO2_DELAY, fx_lfo2_delay},
+ { 3, AWE_FX_LFO2_FREQ, fx_lfo2_freq},
+
+ { 4, AWE_FX_ENV1_DELAY, fx_env1_delay},
+ { 5, AWE_FX_ENV1_ATTACK,fx_env1_attack},
+ { 6, AWE_FX_ENV1_HOLD, fx_env1_hold},
+ { 7, AWE_FX_ENV1_DECAY, fx_env1_decay},
+ { 8, AWE_FX_ENV1_SUSTAIN, fx_env1_sustain},
+ { 9, AWE_FX_ENV1_RELEASE, fx_env1_release},
+
+ {10, AWE_FX_ENV2_DELAY, fx_env2_delay},
+ {11, AWE_FX_ENV2_ATTACK, fx_env2_attack},
+ {12, AWE_FX_ENV2_HOLD, fx_env2_hold},
+ {13, AWE_FX_ENV2_DECAY, fx_env2_decay},
+ {14, AWE_FX_ENV2_SUSTAIN, fx_env2_sustain},
+ {15, AWE_FX_ENV2_RELEASE, fx_env2_release},
+
+ {16, AWE_FX_INIT_PITCH, fx_init_pitch},
+ {17, AWE_FX_LFO1_PITCH, fx_lfo1_pitch},
+ {18, AWE_FX_LFO2_PITCH, fx_lfo2_pitch},
+ {19, AWE_FX_ENV1_PITCH, fx_env1_pitch},
+ {20, AWE_FX_LFO1_VOLUME, fx_lfo1_volume},
+ {21, AWE_FX_CUTOFF, fx_cutoff},
+ {22, AWE_FX_FILTERQ, fx_filterQ},
+ {23, AWE_FX_LFO1_CUTOFF, fx_lfo1_cutoff},
+ {24, AWE_FX_ENV1_CUTOFF, fx_env1_cutoff},
+ {25, AWE_FX_CHORUS, fx_chorus},
+ {26, AWE_FX_REVERB, fx_reverb},
+};
+
+static int num_awe_effects = numberof(awe_effects);
+
+
+/*----------------------------------------------------------------
+ * GS(SC88) NRPN effects; still experimental
+ *----------------------------------------------------------------*/
+
+/* cutoff: quarter semitone step, max=255 */
+static unsigned short gs_cutoff(int val)
+{
+ return (val - 64) * gs_sense[FX_CUTOFF] / 50;
+}
+
+/* resonance: 0 to 15(max) */
+static unsigned short gs_filterQ(int val)
+{
+ return (val - 64) * gs_sense[FX_RESONANCE] / 50;
+}
+
+/* attack: */
+static unsigned short gs_attack(int val)
+{
+ return -(val - 64) * gs_sense[FX_ATTACK] / 50;
+}
+
+/* decay: */
+static unsigned short gs_decay(int val)
+{
+ return -(val - 64) * gs_sense[FX_RELEASE] / 50;
+}
+
+/* release: */
+static unsigned short gs_release(int val)
+{
+ return -(val - 64) * gs_sense[FX_RELEASE] / 50;
+}
+
+/* vibrato freq: 0.042Hz step, max=255 */
+static unsigned short gs_vib_rate(int val)
+{
+ return (val - 64) * gs_sense[FX_VIBRATE] / 50;
+}
+
+/* vibrato depth: max=127, 1 octave */
+static unsigned short gs_vib_depth(int val)
+{
+ return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;
+}
+
+/* vibrato delay: -0.725msec step */
+static unsigned short gs_vib_delay(int val)
+{
+ return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
+}
+
+static ConvTable gs_effects[] =
+{
+ {32, AWE_FX_CUTOFF, gs_cutoff},
+ {33, AWE_FX_FILTERQ, gs_filterQ},
+ {99, AWE_FX_ENV2_ATTACK, gs_attack},
+ {100, AWE_FX_ENV2_DECAY, gs_decay},
+ {102, AWE_FX_ENV2_RELEASE, gs_release},
+ {8, AWE_FX_LFO1_FREQ, gs_vib_rate},
+ {9, AWE_FX_LFO1_VOLUME, gs_vib_depth},
+ {10, AWE_FX_LFO1_DELAY, gs_vib_delay},
+};
+
+static int num_gs_effects = numberof(gs_effects);
+
+
+/*================================================================
+ * NRPN events: accept as AWE32/SC88 specific controls
+ *================================================================*/
+
+static void midi_nrpn_event(MidiStatus *st)
+{
+ if (rpn_msb[st->chan] == 127 && rpn_lsb[st->chan] <= 26) {
+ if (! msb_bit) /* both MSB/LSB necessary */
+ send_converted_effect(awe_effects, num_awe_effects,
+ st, rpn_lsb[st->chan],
+ rpn_val[st->chan] - 8192);
+ } else if (rpn_msb[st->chan] == 1) {
+ if (msb_bit) /* only MSB is valid */
+ add_converted_effect(gs_effects, num_gs_effects,
+ st, rpn_lsb[st->chan],
+ rpn_val[st->chan] / 128);
+ }
+}
+
+
+/*----------------------------------------------------------------
+ * XG control effects; still experimental
+ *----------------------------------------------------------------*/
+
+/* cutoff: quarter semitone step, max=255 */
+static unsigned short xg_cutoff(int val)
+{
+ return (val - 64) * xg_sense[FX_CUTOFF] / 64;
+}
+
+/* resonance: 0(open) to 15(most nasal) */
+static unsigned short xg_filterQ(int val)
+{
+ return (val - 64) * xg_sense[FX_RESONANCE] / 64;
+}
+
+/* attack: */
+static unsigned short xg_attack(int val)
+{
+ return -(val - 64) * xg_sense[FX_ATTACK] / 64;
+}
+
+/* release: */
+static unsigned short xg_release(int val)
+{
+ return -(val - 64) * xg_sense[FX_RELEASE] / 64;
+}
+
+static ConvTable xg_effects[] =
+{
+ {71, AWE_FX_CUTOFF, xg_cutoff},
+ {74, AWE_FX_FILTERQ, xg_filterQ},
+ {72, AWE_FX_ENV2_RELEASE, xg_release},
+ {73, AWE_FX_ENV2_ATTACK, xg_attack},
+};
+
+static int num_xg_effects = numberof(xg_effects);
+
+static int xg_control_change(MidiStatus *st, int cmd, int val)
+{
+ return add_converted_effect(xg_effects, num_xg_effects, st, cmd, val);
+}
+
+#endif /* CONFIG_AWE32_MIDIEMU */
+
+#endif /* CONFIG_AWE32_SYNTH */
diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c
index 489c2c7c0..41533aeda 100644
--- a/drivers/sound/mad16.c
+++ b/drivers/sound/mad16.c
@@ -65,6 +65,8 @@
* Improved debugging support. 16-May-1998
* Fixed bug. 16-Jun-1998
*
+ * Torsten Duwe Made Opti924 PnP support non-destructive
+ * 1998-12-23
*/
#include "sound_config.h"
@@ -279,19 +281,21 @@ static int detect_c930(void)
if ((mad_read(MC0_PORT+13) & 0x80) == 0)
return 1;
+#if 0
/* Force off PnP mode. This is not recommended because
* the PnP bios will not recognize the chip on the next
* warm boot and may assignd different resources to other
* PnP/PCI cards.
*/
mad_write(MC0_PORT+17, 0x04);
+#endif
return 1;
}
static int detect_mad16(void)
{
- unsigned char tmp, tmp2;
- int i;
+ unsigned char tmp, tmp2, bit;
+ int i, port;
/*
* Check that reading a register doesn't return bus float (0xff)
@@ -323,14 +327,19 @@ static int detect_mad16(void)
DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
return 0;
}
- mad_write(MC1_PORT, tmp ^ 0x80); /* Toggle a bit */
- if ((tmp2 = mad_read(MC1_PORT)) != (tmp ^ 0x80)) /* Compare the bit */
+
+ bit = (c924pnp) ? 0x20 : 0x80;
+ port = (c924pnp) ? MC2_PORT : MC1_PORT;
+
+ tmp = mad_read(port);
+ mad_write(port, tmp ^ bit); /* Toggle a bit */
+ if ((tmp2 = mad_read(port)) != (tmp ^ bit)) /* Compare the bit */
{
- mad_write(MC1_PORT, tmp); /* Restore */
+ mad_write(port, tmp); /* Restore */
DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
return 0;
}
- mad_write(MC1_PORT, tmp); /* Restore */
+ mad_write(port, tmp); /* Restore */
return 1; /* Bingo */
}
@@ -456,14 +465,8 @@ static int chip_detect(void)
DDB(printk("Detect using password = 0xE5\n"));
- if (!detect_mad16()) {
- c924pnp++;
- DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
- }
-
if (!detect_mad16()) /* No luck. Try different model */
{
- c924pnp=0;
board_type = C928;
DDB(printk("Detect using password = 0xE2\n"));
@@ -492,11 +495,27 @@ static int chip_detect(void)
for (i = 0xf8d; i <= 0xf93; i++)
DDB(printk("port %03x = %02x\n", i, mad_read(i)));
-
- if (!detect_mad16())
- return 0;
-
- DDB(printk("mad16.c: 82C930 detected\n"));
+ if(!detect_mad16()) {
+
+ /* The C931 has the password reg at F8D */
+ outb((0xE4), 0xF8D);
+ outb((0x80), 0xF8D);
+ DDB(printk("Detect using password = 0xE4 for C931\n"));
+
+ if (!detect_mad16()) {
+ board_type = C924;
+ c924pnp++;
+ DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
+ if (!detect_mad16()) {
+ c924pnp=0;
+ return 0;
+ }
+
+ DDB(printk("mad16.c: 82C924 PnP detected\n"));
+ }
+ }
+ else
+ DDB(printk("mad16.c: 82C930 detected\n"));
} else
DDB(printk("mad16.c: 82C929 detected\n"));
} else {
diff --git a/drivers/sound/midibuf.c b/drivers/sound/midibuf.c
index 7adfeb89c..b1c9763e5 100644
--- a/drivers/sound/midibuf.c
+++ b/drivers/sound/midibuf.c
@@ -40,7 +40,7 @@ struct midi_buf
struct midi_parms
{
- int prech_timeout; /*
+ long prech_timeout; /*
* Timeout before the first ch
*/
};
@@ -282,8 +282,14 @@ int MIDIbuf_write(int dev, struct file *file, const char *buf, int count)
n = SPACE_AVAIL(midi_out_buf[dev]);
if (n == 0) { /*
- * No space just now. We have to sleep
+ * No space just now.
*/
+
+ if (file->f_flags & O_NONBLOCK) {
+ restore_flags(flags);
+ return -EAGAIN;
+ }
+
interruptible_sleep_on(&midi_sleeper[dev]);
if (signal_pending(current))
{
@@ -322,6 +328,10 @@ int MIDIbuf_read(int dev, struct file *file, char *buf, int count)
if (!DATA_AVAIL(midi_in_buf[dev])) { /*
* No data yet, wait
*/
+ if (file->f_flags & O_NONBLOCK) {
+ restore_flags(flags);
+ return -EAGAIN;
+ }
interruptible_sleep_on_timeout(&input_sleeper[dev],
parms[dev].prech_timeout);
diff --git a/drivers/sound/msnd.h b/drivers/sound/msnd.h
index 1dbdedf37..ae7a952ad 100644
--- a/drivers/sound/msnd.h
+++ b/drivers/sound/msnd.h
@@ -24,13 +24,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd.h,v 1.32 1998/10/09 19:54:39 andrewtv Exp $
+ * $Id: msnd.h,v 1.33 1998/11/05 20:26:18 andrewtv Exp $
*
********************************************************************/
#ifndef __MSND_H
#define __MSND_H
-#define VERSION "0.8.2.1"
+#define VERSION "0.8.2.2"
#define DEFSAMPLERATE DSP_DEFAULT_SPEED
#define DEFSAMPLESIZE AFMT_U8
diff --git a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c
index 8f0b6de86..7bf7364ab 100644
--- a/drivers/sound/msnd_pinnacle.c
+++ b/drivers/sound/msnd_pinnacle.c
@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: msnd_pinnacle.c,v 1.66 1998/10/09 19:54:39 andrewtv Exp $
+ * $Id: msnd_pinnacle.c,v 1.73 1998/12/04 14:41:02 andrewtv Exp $
*
********************************************************************/
@@ -67,7 +67,7 @@
#endif
#ifndef CONFIG_MSND_WRITE_NDELAY
-# define CONFIG_MSND_WRITE_NDELAY 0
+# define CONFIG_MSND_WRITE_NDELAY 1
#endif
#define get_play_delay_jiffies(size) ((size) * HZ * \
@@ -379,14 +379,14 @@ static int mixer_get(int d)
switch (d) {
case SOUND_MIXER_VOLUME:
- case SOUND_MIXER_SYNTH:
case SOUND_MIXER_PCM:
case SOUND_MIXER_LINE:
+ case SOUND_MIXER_IMIX:
+ case SOUND_MIXER_LINE1:
#ifndef MSND_CLASSIC
case SOUND_MIXER_MIC:
+ case SOUND_MIXER_SYNTH:
#endif
- case SOUND_MIXER_IMIX:
- case SOUND_MIXER_LINE1:
return (dev.left_levels[d] >> 8) * 100 / 0xff |
(((dev.right_levels[d] >> 8) * 100 / 0xff) << 8);
default:
@@ -394,16 +394,30 @@ static int mixer_get(int d)
}
}
-#define update_vol(a,b,s) \
- writew(dev.left_levels[a] * readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff / s, \
- dev.SMA + SMA_##b##Left); \
- writew(dev.right_levels[a] * readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff / s, \
+#define update_volm(a,b) \
+ writew((dev.left_levels[a] >> 1) * \
+ readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff, \
+ dev.SMA + SMA_##b##Left); \
+ writew((dev.right_levels[a] >> 1) * \
+ readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff, \
dev.SMA + SMA_##b##Right);
-#define update_pot(d,s,ar) \
- writeb(dev.left_levels[d] >> 8, dev.SMA + SMA_##s##Left); \
- writeb(dev.right_levels[d] >> 8, dev.SMA + SMA_##s##Right); \
- if (msnd_send_word(&dev, 0, 0, ar) == 0) \
+#define update_potm(d,s,ar) \
+ writeb((dev.left_levels[d] >> 8) * \
+ readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff, \
+ dev.SMA + SMA_##s##Left); \
+ writeb((dev.right_levels[d] >> 8) * \
+ readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff, \
+ dev.SMA + SMA_##s##Right); \
+ if (msnd_send_word(&dev, 0, 0, ar) == 0) \
+ chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
+
+#define update_pot(d,s,ar) \
+ writeb(dev.left_levels[d] >> 8, \
+ dev.SMA + SMA_##s##Left); \
+ writeb(dev.right_levels[d] >> 8, \
+ dev.SMA + SMA_##s##Right); \
+ if (msnd_send_word(&dev, 0, 0, ar) == 0) \
chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
static int mixer_set(int d, int value)
@@ -412,6 +426,7 @@ static int mixer_set(int d, int value)
int right = (value & 0x0000ff00) >> 8;
int bLeft, bRight;
int wLeft, wRight;
+ int updatemaster = 0;
if (d > 31)
return -EINVAL;
@@ -426,66 +441,66 @@ static int mixer_set(int d, int value)
dev.right_levels[d] = wRight;
switch (d) {
- case SOUND_MIXER_VOLUME: /* master volume */
- writew(wLeft / 2, dev.SMA + SMA_wCurrMastVolLeft);
- writew(wRight / 2, dev.SMA + SMA_wCurrMastVolRight);
- break;
-
- /* pot controls */
- case SOUND_MIXER_LINE: /* aux pot control */
+ /* master volume unscaled controls */
+ case SOUND_MIXER_LINE: /* line pot control */
+ /* scaled by IMIX in digital mix */
writeb(bLeft, dev.SMA + SMA_bInPotPosLeft);
writeb(bRight, dev.SMA + SMA_bInPotPosRight);
if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0)
chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
break;
-
#ifndef MSND_CLASSIC
case SOUND_MIXER_MIC: /* mic pot control */
+ /* scaled by IMIX in digital mix */
writeb(bLeft, dev.SMA + SMA_bMicPotPosLeft);
writeb(bRight, dev.SMA + SMA_bMicPotPosRight);
if (msnd_send_word(&dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0)
chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
break;
#endif
+ case SOUND_MIXER_VOLUME: /* master volume */
+ writew(wLeft, dev.SMA + SMA_wCurrMastVolLeft);
+ writew(wRight, dev.SMA + SMA_wCurrMastVolRight);
+ /* fall through */
- case SOUND_MIXER_LINE1: /* line pot control */
- writeb(bLeft, dev.SMA + SMA_bAuxPotPosLeft);
- writeb(bRight, dev.SMA + SMA_bAuxPotPosRight);
- if (msnd_send_word(&dev, 0, 0, HDEXAR_AUX_SET_POTS) == 0)
- chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
- break;
+ case SOUND_MIXER_LINE1: /* aux pot control */
+ /* scaled by master volume */
+ /* fall through */
/* digital controls */
case SOUND_MIXER_SYNTH: /* synth vol (dsp mix) */
case SOUND_MIXER_PCM: /* pcm vol (dsp mix) */
case SOUND_MIXER_IMIX: /* input monitor (dsp mix) */
+ /* scaled by master volume */
+ updatemaster = 1;
break;
default:
return 0;
}
- /* update digital controls for master volume */
- update_vol(SOUND_MIXER_PCM, wCurrPlayVol, 1);
- update_vol(SOUND_MIXER_IMIX, wCurrInVol, 1);
+ if (updatemaster) {
+ /* update master volume scaled controls */
+ update_volm(SOUND_MIXER_PCM, wCurrPlayVol);
+ update_volm(SOUND_MIXER_IMIX, wCurrInVol);
#ifndef MSND_CLASSIC
- update_vol(SOUND_MIXER_SYNTH, wCurrMHdrVol, 1);
+ update_volm(SOUND_MIXER_SYNTH, wCurrMHdrVol);
#endif
-
+ update_potm(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS);
+ }
+
return mixer_get(d);
}
static void mixer_setup(void)
{
update_pot(SOUND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS);
+ update_potm(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS);
+ update_volm(SOUND_MIXER_PCM, wCurrPlayVol);
+ update_volm(SOUND_MIXER_IMIX, wCurrInVol);
#ifndef MSND_CLASSIC
update_pot(SOUND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS);
-#endif
- update_pot(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS);
- update_vol(SOUND_MIXER_PCM, wCurrPlayVol, 1);
- update_vol(SOUND_MIXER_IMIX, wCurrInVol, 1);
-#ifndef MSND_CLASSIC
- update_vol(SOUND_MIXER_SYNTH, wCurrMHdrVol, 1);
+ update_volm(SOUND_MIXER_SYNTH, wCurrMHdrVol);
#endif
}
@@ -501,7 +516,7 @@ static unsigned long set_recsrc(unsigned long recsrc)
dev.recsrc ^= recsrc;
#ifndef MSND_CLASSIC
- if (dev.recsrc & SOUND_MASK_LINE) {
+ if (dev.recsrc & SOUND_MASK_IMIX) {
if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0)
chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
}
@@ -518,7 +533,7 @@ static unsigned long set_recsrc(unsigned long recsrc)
/* Select no input (?) */
dev.recsrc = 0;
#else
- dev.recsrc = SOUND_MASK_LINE;
+ dev.recsrc = SOUND_MASK_IMIX;
if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0)
chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
#endif
@@ -545,13 +560,15 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
set_mixer_info();
info.modify_counter = dev.mixer_mod_count;
return copy_to_user((void *)arg, &info, sizeof(info));
- }
- else if (cmd == SOUND_OLD_MIXER_INFO) {
+ } else if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info;
set_mixer_info();
return copy_to_user((void *)arg, &info, sizeof(info));
- }
- else if (((cmd >> 8) & 0xff) == 'M') {
+ } else if (cmd == SOUND_MIXER_PRIVATE1) {
+ dev.nresets = 0;
+ dsp_full_reset();
+ return 0;
+ } else if (((cmd >> 8) & 0xff) == 'M') {
int val = 0;
if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
@@ -570,8 +587,7 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
}
++dev.mixer_mod_count;
return put_user(val, (int *)arg);
- }
- else {
+ } else {
switch (cmd & 0xff) {
case SOUND_MIXER_RECSRC:
val = dev.recsrc;
@@ -579,21 +595,22 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
case SOUND_MIXER_DEVMASK:
case SOUND_MIXER_STEREODEVS:
- val = SOUND_MASK_VOLUME |
+ val = SOUND_MASK_PCM |
+ SOUND_MASK_LINE |
+ SOUND_MASK_IMIX |
+ SOUND_MASK_LINE1 |
#ifndef MSND_CLASSIC
- SOUND_MASK_SYNTH |
SOUND_MASK_MIC |
+ SOUND_MASK_SYNTH |
#endif
- SOUND_MASK_PCM |
- SOUND_MASK_LINE |
- SOUND_MASK_IMIX;
+ SOUND_MASK_VOLUME;
break;
case SOUND_MIXER_RECMASK:
#ifdef MSND_CLASSIC
val = 0;
#else
- val = SOUND_MASK_LINE |
+ val = SOUND_MASK_IMIX |
SOUND_MASK_SYNTH;
if (test_bit(F_HAVEDIGITAL, &dev.flags))
val |= SOUND_MASK_DIGITAL1;
@@ -639,7 +656,9 @@ static void dsp_write_flush(void)
if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags))
return;
set_bit(F_WRITEFLUSH, &dev.flags);
- interruptible_sleep_on_timeout(&dev.writeflush, get_play_delay_jiffies(dev.DAPF.len) + HZ / 8);
+ interruptible_sleep_on_timeout(
+ &dev.writeflush,
+ get_play_delay_jiffies(dev.DAPF.len));
clear_bit(F_WRITEFLUSH, &dev.flags);
if (!signal_pending(current)) {
current->state = TASK_INTERRUPTIBLE;
@@ -727,6 +746,16 @@ static void set_default_audio_parameters(void)
set_default_rec_audio_parameters();
}
+static void mod_inc_ref(void)
+{
+ MOD_INC_USE_COUNT;
+}
+
+static void mod_dec_ref(void)
+{
+ MOD_DEC_USE_COUNT;
+}
+
static int dev_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
@@ -760,7 +789,7 @@ static int dev_open(struct inode *inode, struct file *file)
err = -EINVAL;
if (err >= 0)
- MOD_INC_USE_COUNT;
+ mod_inc_ref();
return err;
}
@@ -791,7 +820,7 @@ static int dev_release(struct inode *inode, struct file *file)
if (err >= 0)
#endif
- MOD_DEC_USE_COUNT;
+ mod_dec_ref();
#ifndef LINUX20
return err;
@@ -919,7 +948,9 @@ static int dsp_read(char *buf, size_t len)
if (count > 0) {
set_bit(F_READBLOCK, &dev.flags);
- if (!interruptible_sleep_on_timeout(&dev.readblock, get_rec_delay_jiffies(DAR_BUFF_SIZE)))
+ if (!interruptible_sleep_on_timeout(
+ &dev.readblock,
+ get_rec_delay_jiffies(DAR_BUFF_SIZE)))
clear_bit(F_READING, &dev.flags);
clear_bit(F_READBLOCK, &dev.flags);
if (signal_pending(current))
@@ -960,7 +991,9 @@ static int dsp_write(const char *buf, size_t len)
if (count > 0) {
set_bit(F_WRITEBLOCK, &dev.flags);
- interruptible_sleep_on_timeout(&dev.writeblock, get_play_delay_jiffies(DAP_BUFF_SIZE));
+ interruptible_sleep_on_timeout(
+ &dev.writeblock,
+ get_play_delay_jiffies(DAP_BUFF_SIZE));
clear_bit(F_WRITEBLOCK, &dev.flags);
if (signal_pending(current))
return -EINTR;
@@ -1054,7 +1087,8 @@ static __inline__ void eval_dsp_msg(register WORD wMessage)
break;
default:
-/* printk(KERN_DEBUG LOGNAME ": DSP message %d 0x%02x\n", LOBYTE(wMessage), LOBYTE(wMessage)); */
+/* printk(KERN_DEBUG LOGNAME ": DSP message %d 0x%02x\n",
+ LOBYTE(wMessage), LOBYTE(wMessage)); */
break;
}
break;
@@ -1150,11 +1184,9 @@ __initfunc(static int probe_multisound(void))
return -ENODEV;
}
- printk(KERN_INFO LOGNAME ": DSP reset successful\n");
-
#ifdef MSND_CLASSIC
dev.name = "Classic/Tahiti/Monterey";
- printk(KERN_INFO LOGNAME ": Turtle Beach %s, "
+ printk(KERN_INFO LOGNAME ": %s, "
#else
switch (dev.info >> 4) {
case 0xf: xv = "<= 1.15"; break;
@@ -1177,7 +1209,7 @@ __initfunc(static int probe_multisound(void))
dev.name = pinfiji;
break;
}
- printk(KERN_INFO LOGNAME ": Turtle Beach %s revision %s, Xilinx version %s, "
+ printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, "
#endif /* MSND_CLASSIC */
"I/O 0x%x-0x%x, IRQ %d, memory mapped to 0x%p-0x%p\n",
dev.name,
@@ -1275,26 +1307,20 @@ static int init_sma(void)
__initfunc(static int calibrate_adc(WORD srate))
{
- if (!dev.calibrate_signal) {
- printk(KERN_INFO LOGNAME ": ADC calibration to board ground ");
+ writew(srate, dev.SMA + SMA_wCalFreqAtoD);
+ if (dev.calibrate_signal == 0)
writew(readw(dev.SMA + SMA_wCurrHostStatusFlags)
| 0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
- } else {
- printk(KERN_INFO LOGNAME ": ADC calibration to signal ground ");
+ else
writew(readw(dev.SMA + SMA_wCurrHostStatusFlags)
& ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
- }
-
- writew(srate, dev.SMA + SMA_wCalFreqAtoD);
-
if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ / 3);
- printk("successful\n");
return 0;
}
- printk("failed\n");
+ printk(KERN_WARNING LOGNAME ": ADC calibration failed\n");
return -EIO;
}
@@ -1302,11 +1328,7 @@ __initfunc(static int calibrate_adc(WORD srate))
static int upload_dsp_code(void)
{
outb(HPBLKSEL_0, dev.io + HP_BLKS);
-
-#ifdef HAVE_DSPCODEH
- printk(KERN_INFO LOGNAME ": Using resident Turtle Beach DSP code\n");
-#else
- printk(KERN_INFO LOGNAME ": Loading Turtle Beach DSP code\n");
+#ifndef HAVE_DSPCODEH
INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE);
if (!INITCODE) {
printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);
@@ -1325,6 +1347,11 @@ static int upload_dsp_code(void)
printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");
return -ENODEV;
}
+#ifdef HAVE_DSPCODEH
+ printk(KERN_INFO LOGNAME ": DSP firmware uploaded (resident)\n");
+#else
+ printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n");
+#endif
#ifndef HAVE_DSPCODEH
vfree(INITCODE);
@@ -1365,9 +1392,7 @@ static int initialize(void)
if ((err = upload_dsp_code()) < 0) {
printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
return err;
-
- } else
- printk(KERN_INFO LOGNAME ": DSP upload successful\n");
+ }
timeout = 200;
while (readw(dev.base)) {
@@ -1390,8 +1415,8 @@ static int dsp_full_reset(void)
if (test_bit(F_RESETTING, &dev.flags) || ++dev.nresets > 10)
return 0;
- printk(KERN_INFO LOGNAME ": Resetting DSP\n");
set_bit(F_RESETTING, &dev.flags);
+ printk(KERN_INFO LOGNAME ": DSP reset\n");
dsp_halt(NULL); /* Unconditionally halt */
if ((rv = initialize()))
printk(KERN_WARNING LOGNAME ": DSP reset failed\n");
@@ -1425,7 +1450,7 @@ __initfunc(static int attach_multisound(void))
return err;
}
- if ((dev.dsp_minor = register_sound_dsp(&dev_fileops)) < 0) {
+ if ((dev.dsp_minor = register_sound_dsp(&dev_fileops, -1)) < 0) {
printk(KERN_ERR LOGNAME ": Unable to register DSP operations\n");
msnd_unregister(&dev);
release_region(dev.io, dev.numio);
@@ -1433,7 +1458,7 @@ __initfunc(static int attach_multisound(void))
return dev.dsp_minor;
}
- if ((dev.mixer_minor = register_sound_mixer(&dev_fileops)) < 0) {
+ if ((dev.mixer_minor = register_sound_mixer(&dev_fileops, -1)) < 0) {
printk(KERN_ERR LOGNAME ": Unable to register mixer operations\n");
unregister_sound_mixer(dev.mixer_minor);
msnd_unregister(&dev);
@@ -1441,13 +1466,11 @@ __initfunc(static int attach_multisound(void))
free_irq(dev.irq, &dev);
return dev.mixer_minor;
}
- printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", dev.dsp_minor, dev.mixer_minor);
disable_irq(dev.irq);
calibrate_adc(dev.play_sample_rate);
#ifndef MSND_CLASSIC
- printk(KERN_INFO LOGNAME ": Setting initial recording source to Line In\n");
- force_recsrc(SOUND_MASK_LINE);
+ force_recsrc(SOUND_MASK_IMIX);
#endif
return 0;
@@ -1464,16 +1487,6 @@ static void unload_multisound(void)
}
#endif
-static void mod_inc_ref(void)
-{
- MOD_INC_USE_COUNT;
-}
-
-static void mod_dec_ref(void)
-{
- MOD_DEC_USE_COUNT;
-}
-
#ifndef MSND_CLASSIC
/* Pinnacle/Fiji Logical Device Configuration */
@@ -1896,14 +1909,10 @@ __initfunc(int msnd_pinnacle_init(void))
clear_bit(F_DISABLE_WRITE_NDELAY, &dev.flags);
else
set_bit(F_DISABLE_WRITE_NDELAY, &dev.flags);
-
#ifndef MSND_CLASSIC
- if (digital) {
+ if (digital)
set_bit(F_HAVEDIGITAL, &dev.flags);
- printk(KERN_INFO LOGNAME ": Digital I/O access enabled\n");
- }
#endif
-
init_waitqueue(&dev.writeblock);
init_waitqueue(&dev.readblock);
init_waitqueue(&dev.writeflush);
@@ -1912,9 +1921,7 @@ __initfunc(int msnd_pinnacle_init(void))
#ifndef LINUX20
spin_lock_init(&dev.lock);
#endif
-
- printk(KERN_INFO LOGNAME ": Using %u byte digital audio FIFOs (x2)\n", dev.fifosize);
-
+ printk(KERN_INFO LOGNAME ": %u byte audio FIFOs (x2)\n", dev.fifosize);
if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) {
printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n");
return err;
@@ -1946,10 +1953,7 @@ __initfunc(int msnd_pinnacle_init(void))
#ifdef MODULE
void cleanup_module(void)
{
- printk(KERN_INFO LOGNAME ": Unloading\n");
-
unload_multisound();
-
msnd_fifo_free(&dev.DAPF);
msnd_fifo_free(&dev.DARF);
}
diff --git a/drivers/sound/opl3sa.c b/drivers/sound/opl3sa.c
index 8be3b91a9..341438748 100644
--- a/drivers/sound/opl3sa.c
+++ b/drivers/sound/opl3sa.c
@@ -260,6 +260,7 @@ void unload_opl3sa_wss(struct address_info *hw_config)
hw_config->dma,
dma2,
0);
+ sound_unload_audiodev(hw_config->slots[0]);
}
void unload_opl3sa_mpu(struct address_info *hw_config)
diff --git a/drivers/sound/opl3sa2.c b/drivers/sound/opl3sa2.c
index d9d95c278..2c996da64 100644
--- a/drivers/sound/opl3sa2.c
+++ b/drivers/sound/opl3sa2.c
@@ -1,19 +1,38 @@
/*
* sound/opl3sa2.c
*
- * A low level driver for Yamaha OPL3-SA[2,3,x] based cards.
+ * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
+ * SAx cards should work, as they are just variants of the SA3.
*
- * Scott Murray, Jun 14, 1998
+ * Copyright 1998, 1999 Scott Murray <scottm@interlog.com>
*
- */
-
-/* Based on the CS4232 driver:
+ * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
+ * and others. Now incorporates code/ideas from pss.c, also by Hannu
+ * Savolainen. Both of those files are distributed with the following
+ * license:
+ *
+ * "Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info."
+ *
+ * As such, in accordance with the above license, this file, opl3sa2.c, is
+ * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
+ * See the "COPYING" file distributed with this software for more information.
*
- * Copyright (C) by Hannu Savolainen 1993-1997
+ * Change History
+ * --------------
+ * Scott Murray Original driver (Jun 14, 1998)
+ * Paul J.Y. Lahaie Changed probing / attach code order
+ * Scott Murray Added mixer support (Dec 03, 1998)
+ * Scott Murray Changed detection code to be more forgiving,
+ * added force option as last resort,
+ * fixed ioctl return values. (Dec 30, 1998)
+ * Scott Murray Simpler detection code should work all the time now
+ * (with thanks to Ben Hutchings for the heuristic),
+ * removed now unnecessary force option. (Jan 5, 1999)
*
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
*/
#include <linux/config.h>
@@ -22,8 +41,406 @@
#include "sound_config.h"
#include "soundmodule.h"
+/* Useful control port indexes: */
+#define OPL3SA2_MASTER_LEFT 0x07
+#define OPL3SA2_MASTER_RIGHT 0x08
+#define OPL3SA2_MIC 0x09
+#define OPL3SA2_MISC 0x0A
+
+#define OPL3SA3_WIDE 0x14
+#define OPL3SA3_BASS 0x15
+#define OPL3SA3_TREBLE 0x16
+
+/* Useful constants: */
+#define DEFAULT_VOLUME 50
+#define DEFAULT_MIC 50
+#define DEFAULT_TIMBRE 0
+
+#define CHIPSET_UNKNOWN -1
+
+/*
+ * These are used both as masks against what the card returns,
+ * and as constants.
+ */
+#define CHIPSET_OPL3SA2 1
+#define CHIPSET_OPL3SA3 2
+#define CHIPSET_OPL3SAX 4
+
+
#ifdef CONFIG_OPL3SA2
+/* What's my version? */
+static int chipset = CHIPSET_UNKNOWN;
+
+/* Oh well, let's just cache the name */
+static char chipset_name[16];
+
+/* Where's my mixer */
+static int opl3sa2_mixer = -1;
+
+/* Bag o' mixer data */
+typedef struct opl3sa2_mixerdata {
+ unsigned short cfg_port;
+ unsigned short padding;
+ int ad_mixer_dev;
+ unsigned int volume_l;
+ unsigned int volume_r;
+ unsigned int mic;
+ unsigned int bass;
+ unsigned int treble;
+} opl3sa2_mixerdata;
+
+#ifdef CONFIG_OPL3SA2_CTRL_BASE
+/* Set control port if compiled into the kernel */
+static opl3sa2_mixerdata opl3sa2_data = { CONFIG_OPL3SA2_CTRL_BASE, };
+#else
+static opl3sa2_mixerdata opl3sa2_data;
+#endif
+
+static opl3sa2_mixerdata *devc = &opl3sa2_data;
+
+
+/* Standard read and write functions */
+
+static void opl3sa2_write(unsigned short port,
+ unsigned char index,
+ unsigned char data)
+{
+ outb_p(index, port);
+ outb(data, port + 1);
+}
+
+
+static void opl3sa2_read(unsigned short port,
+ unsigned char index,
+ unsigned char* data)
+{
+ outb_p(index, port);
+ *data = inb(port + 1);
+}
+
+
+/* All of the mixer functions... */
+
+static void opl3sa2_set_volume(opl3sa2_mixerdata *devc, int left, int right)
+{
+ static unsigned char scale[101] = {
+ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
+ 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
+ 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00
+ };
+ unsigned char vol;
+
+ vol = scale[left];
+
+ /* If level is zero, turn on mute */
+ if(!left)
+ vol |= 0x80;
+
+ opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);
+
+ vol = scale[right];
+
+ /* If level is zero, turn on mute */
+ if(!right)
+ vol |= 0x80;
+
+ opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);
+}
+
+
+static void opl3sa2_set_mic(opl3sa2_mixerdata *devc, int level)
+{
+ unsigned char vol = 0x1F;
+
+ if((level >= 0) && (level <= 100))
+ vol = 0x1F - (unsigned char) (0x1F * level / 100L);
+
+ /* If level is zero, turn on mute */
+ if(!level)
+ vol |= 0x80;
+
+ opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);
+}
+
+
+static void opl3sa3_set_bass(opl3sa2_mixerdata *devc, int level)
+{
+ unsigned char bass;
+
+ bass = level ? ((unsigned char) (0x07 * level / 100L)) : 0;
+ bass |= (bass << 4);
+
+ opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
+}
+
+
+static void opl3sa3_set_treble(opl3sa2_mixerdata *devc, int level)
+{
+ unsigned char treble;
+
+ treble = level ? ((unsigned char) (0x07 * level / 100L)) : 0;
+ treble |= (treble << 4);
+
+ opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
+}
+
+
+static void opl3sa2_mixer_reset(opl3sa2_mixerdata *devc)
+{
+ if(devc)
+ {
+ opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
+ devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
+
+ opl3sa2_set_mic(devc, DEFAULT_MIC);
+ devc->mic = DEFAULT_MIC;
+
+ opl3sa3_set_bass(devc, DEFAULT_TIMBRE);
+ opl3sa3_set_treble(devc, DEFAULT_TIMBRE);
+ devc->bass = devc->treble = DEFAULT_TIMBRE;
+ }
+}
+
+
+static void arg_to_volume_mono(unsigned int volume, int *aleft)
+{
+ int left;
+
+ left = volume & 0x00ff;
+ if (left > 100)
+ left = 100;
+ *aleft = left;
+}
+
+
+static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright)
+{
+ arg_to_volume_mono(volume, aleft);
+ arg_to_volume_mono(volume >> 8, aright);
+}
+
+
+static int ret_vol_mono(int left)
+{
+ return ((left << 8) | left);
+}
+
+
+static int ret_vol_stereo(int left, int right)
+{
+ return ((right << 8) | left);
+}
+
+
+static int call_ad_mixer(opl3sa2_mixerdata *devc, unsigned int cmd, caddr_t arg)
+{
+ if(devc->ad_mixer_dev != -1)
+ return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev,
+ cmd,
+ arg);
+ else
+ return -EINVAL;
+}
+
+
+static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+ int cmdf = cmd & 0xff;
+
+ opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
+
+ switch(cmdf)
+ {
+ case SOUND_MIXER_VOLUME:
+ case SOUND_MIXER_MIC:
+ case SOUND_MIXER_BASS:
+ case SOUND_MIXER_TREBLE:
+ case SOUND_MIXER_DEVMASK:
+ case SOUND_MIXER_STEREODEVS:
+ case SOUND_MIXER_RECMASK:
+ case SOUND_MIXER_CAPS:
+ case SOUND_MIXER_RECSRC:
+ break;
+
+ default:
+ return call_ad_mixer(devc, cmd, arg);
+ }
+
+ if(((cmd >> 8) & 0xff) != 'M')
+ return -EINVAL;
+
+ if(_SIOC_DIR (cmd) & _SIOC_WRITE)
+ {
+ switch (cmdf)
+ {
+ case SOUND_MIXER_RECSRC:
+ if(devc->ad_mixer_dev != -1)
+ return call_ad_mixer(devc, cmd, arg);
+ else
+ {
+ if(*(int*)arg != 0)
+ return -EINVAL;
+ return 0;
+ }
+
+ case SOUND_MIXER_VOLUME:
+ arg_to_volume_stereo(*(unsigned int*)arg,
+ &devc->volume_l,
+ &devc->volume_r);
+ opl3sa2_set_volume(devc, devc->volume_l,
+ devc->volume_r);
+ *(int*)arg = ret_vol_stereo(devc->volume_l,
+ devc->volume_r);
+ return 0;
+
+ case SOUND_MIXER_MIC:
+ arg_to_volume_mono(*(unsigned int*)arg,
+ &devc->mic);
+ opl3sa2_set_mic(devc, devc->mic);
+ *(int*)arg = ret_vol_mono(devc->mic);
+ return 0;
+
+ case SOUND_MIXER_BASS:
+ if(chipset != CHIPSET_OPL3SA2)
+ {
+ arg_to_volume_mono(*(unsigned int*)arg,
+ &devc->bass);
+ opl3sa3_set_bass(devc, devc->bass);
+ *(int*)arg = ret_vol_mono(devc->bass);
+ return 0;
+ }
+ return -EINVAL;
+
+ case SOUND_MIXER_TREBLE:
+ if(chipset != CHIPSET_OPL3SA2)
+ {
+ arg_to_volume_mono(*(unsigned int *)arg,
+ &devc->treble);
+ opl3sa3_set_treble(devc, devc->treble);
+ *(int*)arg = ret_vol_mono(devc->treble);
+ return 0;
+ }
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+ }
+ }
+ else
+ {
+ /*
+ * Return parameters
+ */
+ switch (cmdf)
+ {
+ case SOUND_MIXER_DEVMASK:
+ if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
+ *(int*)arg = 0; /* no mixer devices */
+
+ *(int*)arg |= (SOUND_MASK_VOLUME | SOUND_MASK_MIC);
+
+ /* OPL3-SA2 has no bass and treble mixers */
+ if(chipset != CHIPSET_OPL3SA2)
+ *(int*)arg |= (SOUND_MASK_BASS |
+ SOUND_MASK_TREBLE);
+ return 0;
+
+ case SOUND_MIXER_STEREODEVS:
+ if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
+ *(int*)arg = 0; /* no stereo devices */
+ *(int*)arg |= SOUND_MASK_VOLUME;
+ return 0;
+
+ case SOUND_MIXER_RECMASK:
+ if(devc->ad_mixer_dev != -1)
+ {
+ return call_ad_mixer(devc, cmd, arg);
+ }
+ else
+ {
+ /* No recording devices */
+ return (*(int*)arg = 0);
+ }
+
+ case SOUND_MIXER_CAPS:
+ if(devc->ad_mixer_dev != -1)
+ {
+ return call_ad_mixer(devc, cmd, arg);
+ }
+ else
+ {
+ *(int*)arg = SOUND_CAP_EXCL_INPUT;
+ return 0;
+ }
+
+ case SOUND_MIXER_RECSRC:
+ if(devc->ad_mixer_dev != -1)
+ {
+ return call_ad_mixer(devc, cmd, arg);
+ }
+ else
+ {
+ /* No recording source */
+ return (*(int*)arg = 0);
+ }
+
+ case SOUND_MIXER_VOLUME:
+ *(int*)arg = ret_vol_stereo(devc->volume_l,
+ devc->volume_r);
+ return 0;
+
+ case SOUND_MIXER_MIC:
+ *(int*)arg = ret_vol_mono(devc->mic);
+ return 0;
+
+ case SOUND_MIXER_BASS:
+ if(chipset != CHIPSET_OPL3SA2)
+ {
+ *(int*)arg = ret_vol_mono(devc->bass);
+ return 0;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ case SOUND_MIXER_TREBLE:
+ if(chipset != CHIPSET_OPL3SA2)
+ {
+ *(int*)arg = ret_vol_mono(devc->treble);
+ return 0;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+ }
+}
+
+
+static struct mixer_operations opl3sa2_mixer_operations =
+{
+ "Yamaha",
+ "",
+ opl3sa2_mixer_ioctl
+};
+
+/* End of mixer-related stuff */
+
+
int probe_opl3sa2_mpu(struct address_info *hw_config)
{
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
@@ -50,82 +467,143 @@ void unload_opl3sa2_mpu(struct address_info *hw_config)
}
-int probe_opl3sa2_mss(struct address_info *hw_config)
+static int probe_opl3sa2_mss(struct address_info *hw_config)
{
return probe_ms_sound(hw_config);
}
-void attach_opl3sa2_mss(struct address_info *hw_config)
+static void attach_opl3sa2_mss(struct address_info *hw_config)
{
- printk(KERN_INFO "opl3sa2.c: trying to init WSS\n");
-
- attach_ms_sound(hw_config);
+ char mixer_name[64];
+
+ /* Create pretty names for mixer stuff */
+ strncpy(mixer_name, chipset_name, 16);
+ strncat(mixer_name, " and AD1848 (through MSS)", 64);
+
+ strncpy(opl3sa2_mixer_operations.name, chipset_name, 16);
+ strncat(opl3sa2_mixer_operations.name, "-AD1848", 64);
+
+ /* Install master mixer */
+ devc->ad_mixer_dev = -1;
+ if((opl3sa2_mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
+ mixer_name,
+ &opl3sa2_mixer_operations,
+ sizeof(struct mixer_operations),
+ devc)) < 0)
+ {
+ printk(KERN_ERR "Could not install %s master mixer\n", chipset_name);
+ return;
+ }
- /* request_region(hw_config->io_base, 4, "Yamaha 7xx WSS Config"); */
-
- if (hw_config->slots[0] != -1 &&
- audio_devs[hw_config->slots[0]]->mixer_dev != -1)
+ opl3sa2_mixer_reset(devc);
+
+ attach_ms_sound(hw_config); /* Slot 0 */
+ if(hw_config->slots[0] != -1)
{
- AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
- AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
- /* GSM! test the following: */
- AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+ /* Did the MSS driver install? */
+ if(num_mixers == (opl3sa2_mixer + 2))
+ {
+ /* The MSS mixer is installed */
+ devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
+
+ /* Reroute mixers appropiately */
+ AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
+ AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
+ AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+ }
}
}
-void unload_opl3sa2_mss(struct address_info *hw_config)
+static void unload_opl3sa2_mss(struct address_info *hw_config)
{
- int mixer;
-
- /* Find mixer */
- mixer = audio_devs[hw_config->slots[0]]->mixer_dev;
-
- /* Unload MSS audio codec */
unload_ms_sound(hw_config);
-
- sound_unload_audiodev(hw_config->slots[0]);
-
- /* Unload mixer if there */
- if(mixer >= 0)
- {
- sound_unload_mixerdev(mixer);
- }
-
- /* Release MSS config ports */
- release_region(hw_config->io_base, 4);
}
int probe_opl3sa2(struct address_info *hw_config)
{
+ unsigned char version = 0;
+ char tag;
+
/*
* Verify that the I/O port range is free.
*/
-
- printk(KERN_INFO "opl3sa2.c: Control using I/O port 0x%03x\n", hw_config->io_base);
-
- if (check_region(hw_config->io_base, 2))
+ if(check_region(hw_config->io_base, 2))
{
- printk(KERN_ERR "opl3sa2.c: Control I/O port 0x%03x not free\n", hw_config->io_base);
+ printk(KERN_ERR
+ "%s: Control I/O port 0x%03x not free\n",
+ __FILE__,
+ hw_config->io_base);
return 0;
}
- /* GSM!: Add some kind of other test here... */
+ /*
+ * Determine chipset type (SA2, SA3, or SAx)
+ */
- return 1;
+ /*
+ * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
+ */
+ opl3sa2_read(hw_config->io_base,
+ OPL3SA2_MISC,
+ (unsigned char*) &version);
+ version &= 0x07;
+
+ /* Match version number to appropiate chipset */
+ if(version & CHIPSET_OPL3SAX)
+ {
+ chipset = CHIPSET_OPL3SAX;
+ tag = 'x';
+ printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
+ }
+ else
+ {
+ if(version & CHIPSET_OPL3SA3)
+ {
+ chipset = CHIPSET_OPL3SA3;
+ tag = '3';
+ printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
+ }
+ else
+ {
+ if(version & CHIPSET_OPL3SA2)
+ {
+ chipset = CHIPSET_OPL3SA2;
+ tag = '2';
+ printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
+ }
+ else
+ {
+ chipset = CHIPSET_UNKNOWN;
+ tag = '?';
+ printk(KERN_ERR
+ "Unknown Yamaha audio controller version\n");
+ printk(KERN_INFO
+ "%s: chipset version = %x\n",
+ __FILE__,
+ version);
+ }
+ }
+ }
+
+ if(chipset != CHIPSET_UNKNOWN)
+ {
+ /* Generate a pretty name */
+ sprintf(chipset_name, "OPL3-SA%c", tag);
+ return 1;
+ }
+ return 0;
}
void attach_opl3sa2(struct address_info *hw_config)
{
- printk(KERN_INFO "opl3sa2.c: trying to init!\n");
-
- request_region(hw_config->io_base, 2, "Yamaha 7xx Control");
+ request_region(hw_config->io_base, 2, chipset_name);
- /* GSM! Mixer stuff should go here... */
-}
+ devc->cfg_port = hw_config->io_base;
+}
void unload_opl3sa2(struct address_info *hw_config)
@@ -133,7 +611,9 @@ void unload_opl3sa2(struct address_info *hw_config)
/* Release control ports */
release_region(hw_config->io_base, 2);
- /* GSM! Mixer stuff should go here... */
+ /* Unload mixer */
+ if(opl3sa2_mixer >= 0)
+ sound_unload_mixerdev(opl3sa2_mixer);
}
@@ -146,12 +626,26 @@ int irq = -1;
int dma = -1;
int dma2 = -1;
-MODULE_PARM(io,"i");
-MODULE_PARM(mss_io,"i");
-MODULE_PARM(mpu_io,"i");
-MODULE_PARM(irq,"i");
-MODULE_PARM(dma,"i");
-MODULE_PARM(dma2,"i");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
+
+MODULE_PARM(mss_io, "i");
+MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
+
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be on 4 location boundaries and must be from 0x300 to 0x334)");
+
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
+
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
+
+MODULE_PARM(dma2, "i");
+MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
+
+MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
+MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
EXPORT_NO_SYMBOLS;
@@ -159,17 +653,21 @@ struct address_info cfg;
struct address_info mss_cfg;
struct address_info mpu_cfg;
+
/*
- * Install a OPL3SA2 based card. Need to have ad1848 and mpu401
- * loaded ready.
+ * Install a OPL3SA2 based card.
+ *
+ * Need to have ad1848 and mpu401 loaded ready.
*/
int init_module(void)
{
int i;
- if (io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
+ if(io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
{
- printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n");
+ printk(KERN_ERR
+ "%s: io, mss_io, irq, dma, and dma2 must be set.\n",
+ __FILE__);
return -EINVAL;
}
@@ -178,7 +676,7 @@ int init_module(void)
cfg.irq = irq;
cfg.dma = dma;
cfg.dma2 = dma2;
-
+
/* The MSS config: */
mss_cfg.io_base = mss_io;
mss_cfg.irq = irq;
@@ -189,19 +687,20 @@ int init_module(void)
/* Call me paranoid: */
for(i = 0; i < 6; i++)
{
- cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1;
+ cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1;
}
- if (probe_opl3sa2(&cfg) == 0)
+ if(probe_opl3sa2(&cfg) == 0)
{
- return -ENODEV;
+ return -ENODEV;
}
- attach_opl3sa2(&cfg);
- if (probe_opl3sa2_mss(&mss_cfg) == 0)
+ if(probe_opl3sa2_mss(&mss_cfg) == 0)
{
- return -ENODEV;
+ return -ENODEV;
}
+
+ attach_opl3sa2(&cfg);
attach_opl3sa2_mss(&mss_cfg);
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
@@ -213,9 +712,9 @@ int init_module(void)
mpu_cfg.dma = dma;
mpu_cfg.always_detect = 1; /* It's there, so use shared IRQs */
- if (probe_opl3sa2_mpu(&mpu_cfg))
+ if(probe_opl3sa2_mpu(&mpu_cfg))
{
- attach_opl3sa2_mpu(&mpu_cfg);
+ attach_opl3sa2_mpu(&mpu_cfg);
}
}
#endif
@@ -229,7 +728,7 @@ void cleanup_module(void)
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
if(mpu_cfg.slots[1] != -1)
{
- unload_opl3sa2_mpu(&mpu_cfg);
+ unload_opl3sa2_mpu(&mpu_cfg);
}
#endif
unload_opl3sa2_mss(&mss_cfg);
@@ -237,5 +736,5 @@ void cleanup_module(void)
SOUND_LOCK_END;
}
-#endif
-#endif
+#endif /* MODULE */
+#endif /* CONFIG_OPL3SA2 */
diff --git a/drivers/sound/pas2_card.c b/drivers/sound/pas2_card.c
index ab87cae40..488e77a63 100644
--- a/drivers/sound/pas2_card.c
+++ b/drivers/sound/pas2_card.c
@@ -73,12 +73,12 @@ extern void mix_write(unsigned char data, int ioaddr);
unsigned char pas_read(int ioaddr)
{
- return inb(ioaddr ^ translate_code);
+ return inb(ioaddr + translate_code);
}
void pas_write(unsigned char data, int ioaddr)
{
- outb((data), ioaddr ^ translate_code);
+ outb((data), ioaddr + translate_code);
}
/******************* Begin of the Interrupt Handler ********************/
@@ -163,28 +163,34 @@ static int config_pas_hw(struct address_info *hw_config)
if (pas_irq < 0 || pas_irq > 15)
{
printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
+ hw_config->irq=-1;
ok = 0;
}
else
{
int_ptrs = pas_read(0xF38A);
- int_ptrs |= irq_bits[pas_irq] & 0xf;
+ int_ptrs = (int_ptrs & 0xf0) | irq_bits[pas_irq];
pas_write(int_ptrs, 0xF38A);
if (!irq_bits[pas_irq])
{
printk(KERN_ERR "PAS16: Invalid IRQ %d", pas_irq);
+ hw_config->irq=-1;
ok = 0;
}
else
{
- if (request_irq(pas_irq, pasintr, 0, "PAS16",NULL) < 0)
+ if (request_irq(pas_irq, pasintr, 0, "PAS16",hw_config) < 0) {
+ printk(KERN_ERR "PAS16: Cannot allocate IRQ %d\n",pas_irq);
+ hw_config->irq=-1;
ok = 0;
+ }
}
}
if (hw_config->dma < 0 || hw_config->dma > 7)
{
printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
+ hw_config->dma=-1;
ok = 0;
}
else
@@ -193,6 +199,7 @@ static int config_pas_hw(struct address_info *hw_config)
if (!dma_bits[hw_config->dma])
{
printk(KERN_ERR "PAS16: Invalid DMA selection %d", hw_config->dma);
+ hw_config->dma=-1;
ok = 0;
}
else
@@ -200,6 +207,7 @@ static int config_pas_hw(struct address_info *hw_config)
if (sound_alloc_dma(hw_config->dma, "PAS16"))
{
printk(KERN_ERR "pas2_card.c: Can't allocate DMA channel\n");
+ hw_config->dma=-1;
ok = 0;
}
}
@@ -297,7 +305,7 @@ static int detect_pas_hw(struct address_info *hw_config)
outb((0xBC), 0x9A01); /* Activate first board */
outb((hw_config->io_base >> 2), 0x9A01); /* Set base address */
- translate_code = 0x388 ^ hw_config->io_base;
+ translate_code = hw_config->io_base - 0x388;
pas_write(1, 0xBF88); /* Select one wait states */
board_id = pas_read(0x0B8B);
@@ -347,7 +355,7 @@ void attach_pas_card(struct address_info *hw_config)
pas_pcm_init(hw_config);
#endif
-#if !defined(DISABLE_SB_EMULATION) && defined(CONFIG_SB)
+#if !defined(MODULE) && !defined(DISABLE_SB_EMULATION) && defined(CONFIG_SB)
sb_dsp_disable_midi(pas_sb_base); /* No MIDI capability */
#endif
@@ -367,8 +375,20 @@ int probe_pas(struct address_info *hw_config)
void unload_pas(struct address_info *hw_config)
{
- sound_free_dma(hw_config->dma);
- free_irq(hw_config->irq, NULL);
+ extern int pas_audiodev;
+ extern int pas2_mididev;
+
+ if (hw_config->dma>0)
+ sound_free_dma(hw_config->dma);
+ if (hw_config->irq>0)
+ free_irq(hw_config->irq, hw_config);
+
+ if(pas_audiodev!=-1)
+ sound_unload_mixerdev(audio_devs[pas_audiodev]->mixer_dev);
+ if(pas2_mididev!=-1)
+ sound_unload_mididev(pas2_mididev);
+ if(pas_audiodev!=-1)
+ sound_unload_audiodev(pas_audiodev);
}
#ifdef MODULE
diff --git a/drivers/sound/pas2_midi.c b/drivers/sound/pas2_midi.c
index 29203071b..d029d4c4d 100644
--- a/drivers/sound/pas2_midi.c
+++ b/drivers/sound/pas2_midi.c
@@ -21,14 +21,15 @@
static int midi_busy = 0, input_opened = 0;
static int my_dev;
+int pas2_mididev=-1;
+
static unsigned char tmp_queue[256];
static volatile int qlen;
static volatile unsigned char qhead, qtail;
static void (*midi_input_intr) (int dev, unsigned char data);
-static int
-pas_midi_open(int dev, int mode,
+static int pas_midi_open(int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
)
@@ -39,10 +40,8 @@ pas_midi_open(int dev, int mode,
if (midi_busy)
- {
- printk("PAS16: Midi busy\n");
- return -EBUSY;
- }
+ return -EBUSY;
+
/*
* Reset input and output FIFO pointers
*/
@@ -53,10 +52,10 @@ pas_midi_open(int dev, int mode,
cli();
if ((err = pas_set_intr(0x10)) < 0)
- {
- restore_flags(flags);
- return err;
- }
+ {
+ restore_flags(flags);
+ return err;
+ }
/*
* Enable input available and output FIFO empty interrupts
*/
@@ -66,14 +65,14 @@ pas_midi_open(int dev, int mode,
midi_input_intr = input;
if (mode == OPEN_READ || mode == OPEN_READWRITE)
- {
- ctrl |= 0x04; /* Enable input */
- input_opened = 1;
- }
+ {
+ ctrl |= 0x04; /* Enable input */
+ input_opened = 1;
+ }
if (mode == OPEN_WRITE || mode == OPEN_READWRITE)
- {
- ctrl |= 0x08 | 0x10; /* Enable output */
- }
+ {
+ ctrl |= 0x08 | 0x10; /* Enable output */
+ }
pas_write(ctrl, 0x178b);
/*
@@ -89,8 +88,7 @@ pas_midi_open(int dev, int mode,
return 0;
}
-static void
-pas_midi_close(int dev)
+static void pas_midi_close(int dev)
{
/*
@@ -102,35 +100,32 @@ pas_midi_close(int dev)
midi_busy = 0;
}
-static int
-dump_to_midi(unsigned char midi_byte)
+static int dump_to_midi(unsigned char midi_byte)
{
- int fifo_space, x;
+ int fifo_space, x;
fifo_space = ((x = pas_read(0x1B89)) >> 4) & 0x0f;
-/*
- * The MIDI FIFO space register and it's documentation is nonunderstandable.
- * There seem to be no way to differentiate between buffer full and buffer
- * empty situations. For this reason we don't never write the buffer
- * completely full. In this way we can assume that 0 (or is it 15)
- * means that the buffer is empty.
- */
+ /*
+ * The MIDI FIFO space register and it's documentation is nonunderstandable.
+ * There seem to be no way to differentiate between buffer full and buffer
+ * empty situations. For this reason we don't never write the buffer
+ * completely full. In this way we can assume that 0 (or is it 15)
+ * means that the buffer is empty.
+ */
if (fifo_space < 2 && fifo_space != 0) /* Full (almost) */
- {
- return 0; /* Ask upper layers to retry after some time */
- }
+ return 0; /* Ask upper layers to retry after some time */
+
pas_write(midi_byte, 0x178A);
return 1;
}
-static int
-pas_midi_out(int dev, unsigned char midi_byte)
+static int pas_midi_out(int dev, unsigned char midi_byte)
{
- unsigned long flags;
+ unsigned long flags;
/*
* Drain the local queue first
@@ -140,15 +135,15 @@ pas_midi_out(int dev, unsigned char midi_byte)
cli();
while (qlen && dump_to_midi(tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
+ {
+ qlen--;
+ qhead++;
+ }
restore_flags(flags);
/*
- * Output the byte if the local queue is empty.
+ * Output the byte if the local queue is empty.
*/
if (!qlen)
@@ -156,7 +151,7 @@ pas_midi_out(int dev, unsigned char midi_byte)
return 1;
/*
- * Put to the local queue
+ * Put to the local queue
*/
if (qlen >= 256)
@@ -174,25 +169,21 @@ pas_midi_out(int dev, unsigned char midi_byte)
return 1;
}
-static int
-pas_midi_start_read(int dev)
+static int pas_midi_start_read(int dev)
{
return 0;
}
-static int
-pas_midi_end_read(int dev)
+static int pas_midi_end_read(int dev)
{
return 0;
}
-static void
-pas_midi_kick(int dev)
+static void pas_midi_kick(int dev)
{
}
-static int
-pas_buffer_status(int dev)
+static int pas_buffer_status(int dev)
{
return qlen;
}
@@ -218,23 +209,22 @@ static struct midi_operations pas_midi_operations =
NULL
};
-void
-pas_midi_init(void)
+void pas_midi_init(void)
{
- int dev = sound_alloc_mididev();
+ int dev = sound_alloc_mididev();
if (dev == -1)
- {
- printk(KERN_WARNING "pas_midi_init: Too many midi devices detected\n");
- return;
- }
+ {
+ printk(KERN_WARNING "pas_midi_init: Too many midi devices detected\n");
+ return;
+ }
std_midi_synth.midi_dev = my_dev = dev;
midi_devs[dev] = &pas_midi_operations;
+ pas2_mididev = dev;
sequencer_init();
}
-void
-pas_midi_interrupt(void)
+void pas_midi_interrupt(void)
{
unsigned char stat;
int i, incount;
@@ -243,35 +233,35 @@ pas_midi_interrupt(void)
stat = pas_read(0x1B88);
if (stat & 0x04) /* Input data available */
- {
- incount = pas_read(0x1B89) & 0x0f; /* Input FIFO size */
- if (!incount)
- incount = 16;
-
- for (i = 0; i < incount; i++)
- if (input_opened)
- {
- midi_input_intr(my_dev, pas_read(0x178A));
- } else
- pas_read(0x178A); /* Flush */
- }
+ {
+ incount = pas_read(0x1B89) & 0x0f; /* Input FIFO size */
+ if (!incount)
+ incount = 16;
+
+ for (i = 0; i < incount; i++)
+ if (input_opened)
+ {
+ midi_input_intr(my_dev, pas_read(0x178A));
+ } else
+ pas_read(0x178A); /* Flush */
+ }
if (stat & (0x08 | 0x10))
- {
- save_flags(flags);
- cli();
-
- while (qlen && dump_to_midi(tmp_queue[qhead]))
- {
- qlen--;
- qhead++;
- }
-
- restore_flags(flags);
- }
+ {
+ save_flags(flags);
+ cli();
+
+ while (qlen && dump_to_midi(tmp_queue[qhead]))
+ {
+ qlen--;
+ qhead++;
+ }
+
+ restore_flags(flags);
+ }
if (stat & 0x40)
- {
- printk("MIDI output overrun %x,%x\n", pas_read(0x1B89), stat);
- }
+ {
+ printk(KERN_WARNING "MIDI output overrun %x,%x\n", pas_read(0x1B89), stat);
+ }
pas_write(stat, 0x1B88); /* Acknowledge interrupts */
}
diff --git a/drivers/sound/pas2_pcm.c b/drivers/sound/pas2_pcm.c
index 068252002..dc49d04b5 100644
--- a/drivers/sound/pas2_pcm.c
+++ b/drivers/sound/pas2_pcm.c
@@ -42,7 +42,7 @@ static unsigned char pcm_mode = PCM_NON;
static unsigned long pcm_count = 0;
static unsigned short pcm_bitsok = 8; /* mask of OK bits */
static int pcm_busy = 0;
-int pas_audiodev = 0;
+int pas_audiodev = -1;
static int open_mode = 0;
static int pcm_set_speed(int arg)
diff --git a/drivers/sound/pss.c b/drivers/sound/pss.c
index 701be5289..1fa943741 100644
--- a/drivers/sound/pss.c
+++ b/drivers/sound/pss.c
@@ -135,7 +135,7 @@ static void pss_write(pss_confdata *devc, int data)
* loops.
*/
- for (i = 0; i < 5000000 && jiffies < limit; i++)
+ for (i = 0; i < 5000000 && time_before(jiffies, limit); i++)
{
if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY)
{
@@ -285,7 +285,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
outw(0x00fe, REG(PSS_DATA));
limit = jiffies + HZ/10;
- for (i = 0; i < 32768 && jiffies < limit; i++)
+ for (i = 0; i < 32768 && time_before(jiffies, limit); i++)
if (inw(REG(PSS_DATA)) == 0x5500)
break;
diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h
index dc864646e..72ede3fab 100644
--- a/drivers/sound/sb.h
+++ b/drivers/sound/sb.h
@@ -48,8 +48,16 @@
#define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */
#define MDL_AEDSP 15 /* Audio Excel DSP 16 */
+#define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */
+#define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */
+#define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */
+#define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */
+#define SUBMDL_ES1887 0x14 /* Subtype ES1887 for specific handling */
+#define SUBMDL_ES1888 0x14 /* Subtype ES1888 for specific handling */
#define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */
/* register assignment */
+#define SUBMDL_ALS100 43 /* ALS-100 allows sampling rates of up */
+ /* to 48kHz */
/*
* Config flags
*/
@@ -118,7 +126,6 @@ typedef struct sb_devc {
int trg_restart_16;
unsigned char tconst;
- int my_dev;
/* MIDI fields */
int my_mididev;
@@ -129,6 +136,7 @@ typedef struct sb_devc {
} sb_devc;
int sb_dsp_command (sb_devc *devc, unsigned char val);
+int sb_dsp_get_byte(sb_devc * devc);
int sb_dsp_reset (sb_devc *devc);
void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
@@ -141,8 +149,11 @@ void smw_mixer_init(sb_devc *devc);
void sb_dsp_midi_init (sb_devc *devc);
void sb_audio_init (sb_devc *devc, char *name);
void sb_midi_interrupt (sb_devc *devc);
-int ess_write (sb_devc *devc, unsigned char reg, unsigned char data);
-int ess_read (sb_devc *devc, unsigned char reg);
+void sb_chgmixer (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val);
+int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right);
+
+int sb_audio_open(int dev, int mode);
+void sb_audio_close(int dev);
extern int acer;
extern sb_devc *last_sb;
diff --git a/drivers/sound/sb_audio.c b/drivers/sound/sb_audio.c
index b14924e4e..baca53992 100644
--- a/drivers/sound/sb_audio.c
+++ b/drivers/sound/sb_audio.c
@@ -29,7 +29,9 @@
#include "sb_mixer.h"
#include "sb.h"
-static int sb_audio_open(int dev, int mode)
+#include "sb_ess.h"
+
+int sb_audio_open(int dev, int mode)
{
sb_devc *devc = audio_devs[dev]->devc;
unsigned long flags;
@@ -68,6 +70,12 @@ static int sb_audio_open(int dev, int mode)
((mode & OPEN_READ) && (mode & OPEN_WRITE));
sb_dsp_reset(devc);
+ /* At first glance this check isn't enough, some ESS chips might not
+ * have a RECLEV. However if they don't common_mixer_set will refuse
+ * cause devc->iomap has no register mapping for RECLEV
+ */
+ if (devc->model == MDL_ESS) ess_mixer_reload (devc, SOUND_MIXER_RECLEV);
+
/* The ALS007 seems to require that the DSP be removed from the output */
/* in order for recording to be activated properly. This is done by */
/* setting the appropriate bits of the output control register 4ch to */
@@ -87,10 +95,20 @@ static int sb_audio_open(int dev, int mode)
return 0;
}
-static void sb_audio_close(int dev)
+void sb_audio_close(int dev)
{
sb_devc *devc = audio_devs[dev]->devc;
+ /* fix things if mmap turned off fullduplex */
+ if(devc->duplex
+ && !devc->fullduplex
+ && (devc->opened & OPEN_READ) && (devc->opened & OPEN_WRITE))
+ {
+ struct dma_buffparms *dmap_temp;
+ dmap_temp = audio_devs[dev]->dmap_out;
+ audio_devs[dev]->dmap_out = audio_devs[dev]->dmap_in;
+ audio_devs[dev]->dmap_in = dmap_temp;
+ }
audio_devs[dev]->dmap_out->dma = devc->dma8;
audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ?
devc->dma16 : devc->dma8;
@@ -584,256 +602,21 @@ static int jazz16_audio_set_speed(int dev, int speed)
}
/*
- * ESS specific routines
- */
-
-static int ess_audio_set_speed(int dev, int speed)
-{
- sb_devc *devc = audio_devs[dev]->devc;
- int divider;
-
- if (speed > 0)
- {
- if (speed < 5000)
- speed = 5000;
- if (speed > 48000)
- speed = 48000;
-
- if (speed > 22000)
- {
- divider = (795500 + speed / 2) / speed;
- speed = (795500 + divider / 2) / divider;
- }
- else
- {
- divider = (397700 + speed / 2) / speed;
- speed = (397700 + divider / 2) / divider;
- }
- devc->speed = speed;
- }
- return devc->speed;
-}
-
-static void ess_speed(sb_devc * devc)
-{
- int divider;
- unsigned char bits = 0;
- int speed = devc->speed;
-
- if (speed < 4000)
- speed = 4000;
- else if (speed > 48000)
- speed = 48000;
-
- if (speed > 22000)
- {
- bits = 0x80;
- divider = 256 - (795500 + speed / 2) / speed;
- }
- else
- {
- divider = 128 - (397700 + speed / 2) / speed;
- }
-
- bits |= (unsigned char) divider;
- ess_write(devc, 0xa1, bits);
-
- /*
- * Set filter divider register
- */
-
- speed = (speed * 9) / 20; /* Set filter roll-off to 90% of speed/2 */
- divider = 256 - 7160000 / (speed * 82);
- ess_write(devc, 0xa2, divider);
- return;
-}
-
-static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
-{
- sb_devc *devc = audio_devs[dev]->devc;
- ess_speed(devc);
- sb_dsp_command(devc, DSP_CMD_SPKOFF);
-
- ess_write(devc, 0xb8, 0x0e); /* Auto init DMA mode */
- ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels)); /* Mono/stereo */
- ess_write(devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */
-
- if (devc->channels == 1)
- {
- if (devc->bits == AFMT_U8)
- {
- /* 8 bit mono */
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0xd0);
- }
- else
- {
- /* 16 bit mono */
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xf4);
- }
- }
- else
- {
- /* Stereo */
- if (devc->bits == AFMT_U8)
- {
- /* 8 bit stereo */
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0x98);
- }
- else
- {
- /* 16 bit stereo */
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xbc);
- }
- }
- ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
- ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
- devc->trigger_bits = 0;
- return 0;
-}
-
-static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
-{
- sb_devc *devc = audio_devs[dev]->devc;
-
- sb_dsp_reset(devc);
- ess_speed(devc);
-
- ess_write(devc, 0xb8, 4); /* Auto init DMA mode */
- ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels)); /* Mono/stereo */
- ess_write(devc, 0xb9, 2); /* Demand mode (4 bytes/request) */
-
- if (devc->channels == 1)
- {
- if (devc->bits == AFMT_U8)
- { /* 8 bit mono */
- ess_write(devc, 0xb6, 0x80);
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0xd0);
- }
- else
- { /* 16 bit mono */
- ess_write(devc, 0xb6, 0x00);
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xf4);
- }
- }
- else
- { /* Stereo */
- if (devc->bits == AFMT_U8)
- { /* 8 bit stereo */
- ess_write(devc, 0xb6, 0x80);
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0x98);
- }
- else
- { /* 16 bit stereo */
- ess_write(devc, 0xb6, 0x00);
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xbc);
- }
- }
-
- ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
- ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
- sb_dsp_command(devc, DSP_CMD_SPKON);
-
- devc->trigger_bits = 0;
- return 0;
-}
-
-static void ess_audio_output_block(int dev, unsigned long buf, int nr_bytes,
- int intrflag)
-{
- int count = nr_bytes;
- sb_devc *devc = audio_devs[dev]->devc;
- short c = -nr_bytes;
-
- /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
-
- if (audio_devs[dev]->dmap_out->dma > 3)
- count >>= 1;
- count--;
-
- devc->irq_mode = IMODE_OUTPUT;
-
- ess_write(devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
- ess_write(devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-
- ess_write(devc, 0xb8, ess_read(devc, 0xb8) | 0x05); /* Go */
- devc->intr_active = 1;
-}
-
-static void ess_audio_start_input(int dev, unsigned long buf, int nr_bytes, int intrflag)
-{
- int count = nr_bytes;
- sb_devc *devc = audio_devs[dev]->devc;
- short c = -nr_bytes;
-
- /*
- * Start a DMA input to the buffer pointed by dmaqtail
- */
-
- /* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
-
- if (audio_devs[dev]->dmap_out->dma > 3)
- count >>= 1;
- count--;
-
- devc->irq_mode = IMODE_INPUT;
-
- ess_write(devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
- ess_write(devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-
- ess_write(devc, 0xb8, ess_read(devc, 0xb8) | 0x0f); /* Go */
- devc->intr_active = 1;
-}
-
-static void ess_audio_trigger(int dev, int bits)
-{
- sb_devc *devc = audio_devs[dev]->devc;
-
- bits &= devc->irq_mode;
-
- if (!bits)
- sb_dsp_command(devc, 0xd0); /* Halt DMA */
- else
- {
- switch (devc->irq_mode)
- {
- case IMODE_INPUT:
- ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
- devc->trg_intrflag);
- break;
-
- case IMODE_OUTPUT:
- ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
- devc->trg_intrflag);
- break;
- }
- }
-
- devc->trigger_bits = bits;
-}
-
-/*
* SB16 specific routines
*/
static int sb16_audio_set_speed(int dev, int speed)
{
sb_devc *devc = audio_devs[dev]->devc;
+ int max_speed = devc->submodel == SUBMDL_ALS100 ? 48000 : 44100;
if (speed > 0)
{
- if (speed < 5000)
- speed = 4000;
+ if (speed < 5000) /* which of these */
+ speed = 4000; /* is correct ??? */
- if (speed > 44100)
- speed = 44100;
+ if (speed > max_speed)
+ speed = max_speed;
devc->speed = speed;
}
@@ -1136,6 +919,12 @@ sb16_copy_from_user(int dev,
}
}
+static void
+sb16_audio_mmap(int dev)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+ devc->fullduplex = 0;
+}
static struct audio_driver sb1_audio_driver = /* SB1.x */
{
@@ -1254,27 +1043,10 @@ static struct audio_driver sb16_audio_driver = /* SB16 */
sb16_audio_trigger,
sb16_audio_set_speed,
sb16_audio_set_bits,
- sbpro_audio_set_channels
-};
-
-static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */
-{
- sb_audio_open,
- sb_audio_close,
- sb_set_output_parms,
- sb_set_input_parms,
- NULL,
- ess_audio_prepare_for_input,
- ess_audio_prepare_for_output,
- sb1_audio_halt_xfer,
- NULL, /* local_qlen */
- NULL, /* copy_from_user */
+ sbpro_audio_set_channels,
NULL,
NULL,
- ess_audio_trigger,
- ess_audio_set_speed,
- sb16_audio_set_bits,
- sbpro_audio_set_channels
+ sb16_audio_mmap
};
void sb_audio_init(sb_devc * devc, char *name)
@@ -1313,9 +1085,7 @@ void sb_audio_init(sb_devc * devc, char *name)
case MDL_ESS:
DDB(printk("Will use ESS ES688/1688 driver\n"));
- audio_flags = DMA_AUTOMODE;
- format_mask |= AFMT_S16_LE;
- driver = &ess_audio_driver;
+ driver = ess_audio_init (devc, &audio_flags, &format_mask);
break;
case MDL_SB16:
@@ -1336,17 +1106,17 @@ void sb_audio_init(sb_devc * devc, char *name)
driver = &sbpro_audio_driver;
}
- if ((devc->my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
+ if ((devc->dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
name,driver, sizeof(struct audio_driver),
audio_flags, format_mask, devc,
devc->dma8,
- devc->duplex ? devc->dma16 : devc->dma8) < 0))
+ devc->duplex ? devc->dma16 : devc->dma8)) < 0)
{
printk(KERN_ERR "Sound Blaster: unable to install audio.\n");
return;
}
- audio_devs[devc->my_dev]->mixer_dev = devc->my_mixerdev;
- audio_devs[devc->my_dev]->min_fragment = 5;
+ audio_devs[devc->dev]->mixer_dev = devc->my_mixerdev;
+ audio_devs[devc->dev]->min_fragment = 5;
}
#endif
diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c
index 24a3aa829..b85db519c 100644
--- a/drivers/sound/sb_card.c
+++ b/drivers/sound/sb_card.c
@@ -113,6 +113,7 @@ void unload_sb(struct address_info *hw_config)
}
int sb_be_quiet=0;
+int esstype = 0; /* ESS chip type */
#ifdef MODULE
@@ -147,6 +148,7 @@ MODULE_PARM(mad16, "i");
MODULE_PARM(trix, "i");
MODULE_PARM(pas2, "i");
MODULE_PARM(sm_games, "i");
+MODULE_PARM(esstype, "i");
void *smw_free = NULL;
diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c
index 34f82ff70..907250981 100644
--- a/drivers/sound/sb_common.c
+++ b/drivers/sound/sb_common.c
@@ -13,6 +13,8 @@
/*
* Daniel J. Rodriksson: Modified sbintr to handle 8 and 16 bit interrupts
* for full duplex support ( only sb16 by now )
+ * Rolf Fokkens: Added (BETA?) support for ES1887 chips.
+ * (fokkensr@vertis.nl) Which means: You can adjust the recording levels.
*/
#include <linux/config.h>
#include <linux/delay.h>
@@ -30,6 +32,8 @@
#include "sb_mixer.h"
#include "sb.h"
+#include "sb_ess.h"
+
static sb_devc *detected_devc = NULL; /* For communication from probe to init */
static sb_devc *last_devc = NULL; /* For MPU401 initialization */
@@ -89,7 +93,7 @@ int sb_dsp_command(sb_devc * devc, unsigned char val)
return 0;
}
-static int sb_dsp_get_byte(sb_devc * devc)
+int sb_dsp_get_byte(sb_devc * devc)
{
int i;
@@ -101,43 +105,18 @@ static int sb_dsp_get_byte(sb_devc * devc)
return 0xffff;
}
-int ess_write(sb_devc * devc, unsigned char reg, unsigned char data)
-{
- /* Write a byte to an extended mode register of ES1688 */
-
- if (!sb_dsp_command(devc, reg))
- return 0;
-
- return sb_dsp_command(devc, data);
-}
-
-int ess_read(sb_devc * devc, unsigned char reg)
-{
-/* Read a byte from an extended mode register of ES1688 */
- if (!sb_dsp_command(devc, 0xc0)) /* Read register command */
- return -1;
-
- if (!sb_dsp_command(devc, reg))
- return -1;
-
- return sb_dsp_get_byte(devc);
-}
-
-static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+static void sb_intr (sb_devc *devc)
{
int status;
unsigned char src = 0xff;
- sb_devc *devc = dev_id;
-
- devc->irq_ok = 1;
if (devc->model == MDL_SB16)
{
src = sb_getmixer(devc, IRQ_STAT); /* Interrupt source register */
#if defined(CONFIG_MIDI)&& defined(CONFIG_UART401)
- if (src & 4)
- uart401intr(devc->irq, devc->midi_irq_cookie, NULL); /* MPU401 interrupt */
+ if (src & 4) /* MPU401 interrupt */
+ uart401intr(devc->irq, devc->midi_irq_cookie, NULL);
#endif
if (!(src & 3))
@@ -200,6 +179,21 @@ static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
status = inb(DSP_DATA_AVL16);
}
+static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
+{
+ sb_devc *devc = dev_id;
+
+ devc->irq_ok = 1;
+
+ switch (devc->model) {
+ case MDL_ESS:
+ ess_intr (devc);
+ break;
+ default:
+ sb_intr (devc);
+ break;
+ }
+}
int sb_dsp_reset(sb_devc * devc)
{
@@ -207,10 +201,11 @@ int sb_dsp_reset(sb_devc * devc)
DEB(printk("Entered sb_dsp_reset()\n"));
- if (devc->model == MDL_ESS)
- outb(3, DSP_RESET); /* Reset FIFO too */
- else
- outb(1, DSP_RESET);
+ if (devc->model == MDL_ESS) return ess_dsp_reset (devc);
+
+ /* This is only for non-ESS chips */
+
+ outb(1, DSP_RESET);
udelay(10);
outb(0, DSP_RESET);
@@ -223,10 +218,9 @@ int sb_dsp_reset(sb_devc * devc)
DDB(printk("sb: No response to RESET\n"));
return 0; /* Sorry */
}
- if (devc->model == MDL_ESS)
- sb_dsp_command(devc, 0xc6); /* Enable extended mode */
DEB(printk("sb_dsp_reset() OK\n"));
+
return 1;
}
@@ -484,132 +478,6 @@ static void relocate_ess1688(sb_devc * devc)
#endif
}
-static int ess_init(sb_devc * devc, struct address_info *hw_config)
-{
- unsigned char cfg, irq_bits = 0, dma_bits = 0;
- int ess_major = 0, ess_minor = 0;
- int i;
- static char name[100];
-
- /*
- * Try to detect ESS chips.
- */
-
- sb_dsp_command(devc, 0xe7); /* Return identification */
-
- for (i = 1000; i; i--)
- {
- if (inb(DSP_DATA_AVAIL) & 0x80)
- {
- if (ess_major == 0)
- ess_major = inb(DSP_READ);
- else
- {
- ess_minor = inb(DSP_READ);
- break;
- }
- }
- }
-
- if (ess_major == 0)
- return 0;
-
- if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80)
- {
- sprintf(name, "ESS ES488 AudioDrive (rev %d)",
- ess_minor & 0x0f);
- hw_config->name = name;
- devc->model = MDL_SBPRO;
- return 1;
- }
- else if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80)
- {
- char *chip = "ES688";
-
- if ((ess_minor & 0x0f) >= 8)
- chip = "ES1688";
-
- sprintf(name,"ESS %s AudioDrive (rev %d)",
- chip, ess_minor & 0x0f);
- }
- else
- strcpy(name, "Jazz16");
-
- devc->model = MDL_ESS;
- devc->submodel = ess_minor & 0x0f;
- hw_config->name = name;
- sb_dsp_reset(devc); /* Turn on extended mode */
-
- /*
- * Set IRQ configuration register
- */
-
- cfg = 0x50; /* Enable only DMA counter interrupt */
-
- switch (devc->irq)
- {
- case 2:
- case 9:
- irq_bits = 0;
- break;
-
- case 5:
- irq_bits = 1;
- break;
-
- case 7:
- irq_bits = 2;
- break;
-
- case 10:
- irq_bits = 3;
- break;
-
- default:
- irq_bits = 0;
- cfg = 0x10; /* Disable all interrupts */
- printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", devc->irq);
- return 0;
- }
-
- if (!ess_write(devc, 0xb1, cfg | (irq_bits << 2)))
- printk(KERN_ERR "ESS1688: Failed to write to IRQ config register\n");
-
- /*
- * Set DMA configuration register
- */
-
- cfg = 0x50; /* Extended mode DMA enable */
-
- if (devc->dma8 > 3 || devc->dma8 < 0 || devc->dma8 == 2)
- {
- dma_bits = 0;
- cfg = 0x00; /* Disable all DMA */
- printk(KERN_ERR "ESS1688: Invalid DMA %d\n", devc->dma8);
- }
- else
- {
- if (devc->dma8 == 3)
- dma_bits = 3;
- else
- dma_bits = devc->dma8 + 1;
- }
-
- if (!ess_write(devc, 0xb2, cfg | (dma_bits << 2)))
- printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n");
-
- /*
- * Enable joystick and OPL3
- */
-
- cfg = sb_getmixer(devc, 0x40);
- sb_setmixer(devc, 0x40, cfg | 0x03);
- if (devc->submodel >= 8) /* ES1688 */
- devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
- sb_dsp_reset(devc);
- return 1;
-}
-
int sb_dsp_detect(struct address_info *hw_config)
{
sb_devc sb_info;
@@ -618,7 +486,7 @@ int sb_dsp_detect(struct address_info *hw_config)
memset((char *) &sb_info, 0, sizeof(sb_info)); /* Zero everything */
sb_info.my_mididev = -1;
sb_info.my_mixerdev = -1;
- sb_info.my_dev = -1;
+ sb_info.dev = -1;
/*
* Initialize variables
@@ -713,7 +581,7 @@ int sb_dsp_detect(struct address_info *hw_config)
return 0;
}
memcpy((char *) detected_devc, (char *) devc, sizeof(sb_devc));
- MDB(printk("SB %d.%d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
+ MDB(printk(KERN_INFO "SB %d.%d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
return 1;
}
@@ -777,10 +645,6 @@ int sb_dsp_init(struct address_info *hw_config)
}
}
}
-#if defined(__SMP__)
- /* Skip IRQ detection if SMP (doesn't work) */
- devc->irq_ok = 1;
-#else
if (devc->major == 4 && devc->minor <= 11 ) /* Won't work */
devc->irq_ok = 1;
else
@@ -803,7 +667,6 @@ int sb_dsp_init(struct address_info *hw_config)
DDB(printk("IRQ test OK (IRQ%d)\n", devc->irq));
}
}
-#endif /* __SMP__ */
} /* IRQ setup */
request_region(hw_config->io_base, 16, "soundblaster");
@@ -823,11 +686,18 @@ int sb_dsp_init(struct address_info *hw_config)
break;
case 3: /* SB Pro and most clones */
- if (devc->model == 0)
- {
+ switch (devc->model) {
+ case 0:
devc->model = hw_config->card_subtype = MDL_SBPRO;
if (hw_config->name == NULL)
hw_config->name = "Sound Blaster Pro (8 BIT ONLY)";
+ break;
+ case MDL_ESS:
+ if (!ess_dsp_init(devc, hw_config)) {
+ release_region (hw_config->io_base, 16);
+ return 0;
+ }
+ break;
}
break;
@@ -849,6 +719,7 @@ int sb_dsp_init(struct address_info *hw_config)
/* Register 0x22 & 0xf0 on ALS100 == 0xf0; on ALS007 it == 0x10. */
if ((sb_getmixer(devc,0x30) != 0xff) || ((sb_getmixer(devc,0x22) & 0xf0) != 0x10))
{
+ devc->submodel = SUBMDL_ALS100;
if (hw_config->name == NULL)
hw_config->name = "Sound Blaster 16 (ALS-100)";
}
@@ -975,16 +846,18 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
if (devc->dma16 >= 0)
sound_free_dma(devc->dma16);
}
- if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && devc->irq > 0)
+ if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI))
{
- free_irq(devc->irq, devc);
+ if (devc->irq > 0);
+ free_irq(devc->irq, devc);
+
sound_unload_mixerdev(devc->my_mixerdev);
/* We don't have to do this bit any more the UART401 is its own
master -- Krzysztof Halasa */
/* But we have to do it, if UART401 is not detected */
if (!sbmpu)
sound_unload_mididev(devc->my_mididev);
- sound_unload_audiodev(devc->my_dev);
+ sound_unload_audiodev(devc->dev);
}
kfree(devc);
}
@@ -996,19 +869,25 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
/*
* Mixer access routines
+ *
+ * ES1887 modifications: some mixer registers reside in the
+ * range above 0xa0. These must be accessed in another way.
*/
void sb_setmixer(sb_devc * devc, unsigned int port, unsigned int value)
{
unsigned long flags;
+ if (devc->model == MDL_ESS) return ess_setmixer (devc, port, value);
+
save_flags(flags);
cli();
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
udelay(20);
outb(((unsigned char) (value & 0xff)), MIXER_DATA);
udelay(20);
+
restore_flags(flags);
}
@@ -1017,18 +896,31 @@ unsigned int sb_getmixer(sb_devc * devc, unsigned int port)
unsigned int val;
unsigned long flags;
+ if (devc->model == MDL_ESS) return ess_getmixer (devc, port);
+
save_flags(flags);
cli();
- outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
udelay(20);
val = inb(MIXER_DATA);
udelay(20);
+
restore_flags(flags);
return val;
}
+void sb_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = sb_getmixer(devc, reg);
+ value = (value & ~mask) | (val & mask);
+ sb_setmixer(devc, reg, value);
+}
+
#ifdef CONFIG_MIDI
/*
@@ -1172,53 +1064,6 @@ static int smw_midi_init(sb_devc * devc, struct address_info *hw_config)
return 1;
}
-static int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
-{
- unsigned char cfg, tmp;
-
- cfg = sb_getmixer(devc, 0x40) & 0x03;
-
- if (devc->submodel < 8)
- {
- sb_setmixer(devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */
- return 0; /* ES688 doesn't support MPU401 mode */
- }
- tmp = (hw_config->io_base & 0x0f0) >> 4;
-
- if (tmp > 3)
- {
- sb_setmixer(devc, 0x40, cfg);
- return 0;
- }
- cfg |= tmp << 3;
-
- tmp = 1; /* MPU enabled without interrupts */
-
- /* May be shared: if so the value is -ve */
-
- switch(abs(hw_config->irq))
- {
- case 9:
- tmp = 0x4;
- break;
- case 5:
- tmp = 0x5;
- break;
- case 7:
- tmp = 0x6;
- break;
- case 10:
- tmp = 0x7;
- break;
- default:
- return 0;
- }
-
- cfg |= tmp << 5;
- sb_setmixer(devc, 0x40, cfg | 0x03);
- return 1;
-}
-
static int init_Jazz16_midi(sb_devc * devc, struct address_info *hw_config)
{
int mpu_base = hw_config->io_base;
diff --git a/drivers/sound/sb_ess.c b/drivers/sound/sb_ess.c
new file mode 100644
index 000000000..d1fdd4ccb
--- /dev/null
+++ b/drivers/sound/sb_ess.c
@@ -0,0 +1,1732 @@
+/*
+ * Created: 9-Jan-1999
+ *
+ * TODO: consistency speed calculations!!
+ * ????: Did I break MIDI support?
+ *
+ * This files contains ESS chip specifics. It's based on the existing ESS
+ * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
+ * file adds features like:
+ * - Chip Identification (as shown in /proc/sound)
+ * - RECLEV support for ES1688 and later
+ * - 6 bits playback level support chips later than ES1688
+ * - Recording level support on a per-device basis for ES1887
+ * - Full-Duplex for ES1887 (under development)
+ *
+ * Full duplex is enabled by specifying dma16. While the normal dma must
+ * be one of 0, 1 or 3, dma16 can be one of 0, 1, 3 or 5. DMA 5 is a 16 bit
+ * DMA channel, while the others are 8 bit..
+ *
+ * ESS detection isn't full proof (yet). If it fails an additional module
+ * parameter esstype can be specified to be one of the following:
+ * 688, 1688, 1868, 1869, 1788, 1887, 1888
+ *
+ * History:
+ *
+ * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per
+ * input basis.
+ * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888,
+ * ES1868, ES1869 and ES1878. Could be used for
+ * specific handling in the future. All except
+ * ES1887 and ES1888 and ES688 are handled like
+ * ES1688.
+ * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now
+ * have the "Dec 20" support + RECLEV
+ * (jan 2 1999): Preparation for Full Duplex. This means
+ * Audio 2 is now used for playback when dma16
+ * is specified. The next step would be to use
+ * Audio 1 and Audio 2 at the same time.
+ */
+
+#undef FKS_LOGGING
+
+/*
+ * About the documentation
+ *
+ * I don't know if the chips all are OK, but the documentation is buggy. 'cause
+ * I don't have all the cips myself, there's a lot I cannot verify. I'll try to
+ * keep track of my latest insights about his here. If you have additional info,
+ * please enlighten me (fokkensr@vertis.nl)!
+ *
+ * I had the impression that ES1688 also has 6 bit master volume control. The
+ * documentation about ES1888 (rev C, october '95) claims that ES1888 has
+ * the following features ES1688 doesn't have:
+ * - 6 bit master volume
+ * - Full Duplex
+ * So ES1688 apparently doesn't have 6 bit master volume control, but the
+ * ES1688 does have RECLEV control. Makes me wonder: does ES688 have it too?
+ * Without RECLEV ES688 won't be much fun I guess.
+ *
+ * From the ES1888 (rev C, october '95) documentation I got the impression
+ * that registers 0x68 to 0x6e don't exist which means: no recording volume
+ * controls. To my surprise the ES888 documentation (1/14/96) claims that
+ * ES888 does have these record mixer registers, but that ES1888 doesn't have
+ * 0x69 and 0x6b. So the rest should be there.
+ *
+ * I'm trying to get ES1887 Full Duplex. Audio 2 is playback only, while Audio 2
+ * is both record and playback. I think I should use Audio 2 for all playback.
+ *
+ * The documentation is an adventure: it's close but not fully accurate. I
+ * found out that after a reset some registers are *NOT* reset, though the
+ * docs say the would be. Interresting ones are 0x7f, 0x7d and 0x7a. They are
+ * related to the Audio 2 channel. I also was suprised about the consequenses
+ * of writing 0x00 to 0x7f (which should be done by reset): The ES1887 moves
+ * into ES1888 mode. This means that it claims IRQ 11, which happens to be my
+ * ISDN adapter. Needless to say it no longer worked. I now understand why
+ * after rebooting 0x7f already was 0x05, the value of my choise: the BIOS
+ * did it.
+ *
+ * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is decribed
+ * as if it's exactly the same as register 0xa1. This is *NOT* true. The
+ * description of 0x70 in ES1869 docs is accurate however.
+ * Well, the assumption about ES1869 was wrong: register 0x70 is very much
+ * like register 0xa1, except that bit 7 is allways 1, whatever you want
+ * it to be.
+ *
+ * When using audio 2 mixer register 0x72 seems te be meaningless. Only 0xa2
+ * has effect.
+ *
+ * Software reset not being able to reset all registers is great! Especially
+ * the fact that register 0x78 isn't reset is great when you wanna change back
+ * to single dma operation (simplex): audio 2 is still operation, and uses the
+ * same dma as audio 1: your ess changes into a funny echo machine.
+ *
+ * Received the new that ES1688 is detected as a ES1788. Did some thinking:
+ * the ES1887 detection scheme suggests in step 2 to try if bit 3 of register
+ * 0x64 can be changed. This is inaccurate, first I inverted the * check: "If
+ * can be modified, it's a 1688", which lead to a correct detection
+ * of my ES1887. It resulted however in bad detection of 1688 (reported by mail)
+ * and 1868 (if no PnP detection first): they result in a 1788 being detected.
+ * I don't have docs on 1688, but I do have docs on 1868: The documentation is
+ * probably inaccurate in the fact that I should check bit 2, not bit 3. This
+ * is what I do now.
+ */
+
+/*
+ * About recognition of ESS chips
+ *
+ * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in
+ * a (preliminary ??) datasheet on ES1887. It's aim is to identify ES1887, but
+ * during detection the text claims that "this chip may be ..." when a step
+ * fails. This scheme is used to distinct between the above chips.
+ * It appears however that some PnP chips like ES1868 are recognized as ES1788
+ * by the ES1887 detection scheme. These PnP chips can be detected in another
+ * way however: ES1868, ES1869 and ES1878 can be recognized (full proof I think)
+ * by repeatedly reading mixer register 0x40. This is done by ess_identify in
+ * sb_common.c.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ * if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878
+ * if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788
+ * if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
+ * About RECLEV support:
+ *
+ * The existing ES1688 support didn't take care of the ES1688+ recording
+ * levels very well. Whenever a device was selected (recmask) for recording
+ * it's recording level was loud, and it couldn't be changed. The fact that
+ * internal register 0xb4 could take care of RECLEV, didn't work meaning until
+ * it's value was restored every time the chip was reset; this reset the
+ * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with.
+ *
+ * About ES1887 support:
+ *
+ * The ES1887 has separate registers to control the recording levels, for all
+ * inputs. The ES1887 specific software makes these levels the same as their
+ * corresponding playback levels, unless recmask says they aren't recorded. In
+ * the latter case the recording volumes are 0.
+ * Now recording levels of inputs can be controlled, by changing the playback
+ * levels. Futhermore several devices can be recorded together (which is not
+ * possible with the ES1688.
+ * Besides the separate recording level control for each input, the common
+ * recordig level can also be controlled by RECLEV as described above.
+ *
+ * Not only ES1887 have this recording mixer. I know the following from the
+ * documentation:
+ * ES688 no
+ * ES1688 no
+ * ES1868 no
+ * ES1869 yes
+ * ES1878 no
+ * ES1879 yes
+ * ES1888 no/yes Contradicting documentation; most recent: yes
+ * ES1946 yes This is a PCI chip; not handled by this driver
+ */
+
+#include "sound_config.h"
+#include "sb_mixer.h"
+#include "sb.h"
+
+#include "sb_ess.h"
+
+extern int esstype; /* module parameter in sb_card.c */
+
+#ifdef FKS_LOGGING
+static void ess_show_mixerregs (sb_devc *devc);
+#endif
+static int ess_read (sb_devc * devc, unsigned char reg);
+static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data);
+static void ess_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val);
+
+/****************************************************************************
+ * *
+ * ESS audio *
+ * *
+ ****************************************************************************/
+
+struct ess_command {short cmd; short data;};
+
+/*
+ * Commands for initializing Audio 1 for input (record)
+ */
+static struct ess_command ess_i08m[] = /* input 8 bit mono */
+ { {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_i16m[] = /* input 16 bit mono */
+ { {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_i08s[] = /* input 8 bit stereo */
+ { {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_i16s[] = /* input 16 bit stereo */
+ { {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+static struct ess_command *ess_inp_cmds[] =
+ { ess_i08m, ess_i16m, ess_i08s, ess_i16s };
+
+
+/*
+ * Commands for initializing Audio 1 for output (playback)
+ */
+static struct ess_command ess_o08m[] = /* output 8 bit mono */
+ { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_o16m[] = /* output 16 bit mono */
+ { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_o08s[] = /* output 8 bit stereo */
+ { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_o16s[] = /* output 16 bit stereo */
+ { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+static struct ess_command *ess_out_cmds[] =
+ { ess_o08m, ess_o16m, ess_o08s, ess_o16s };
+
+static void ess_exec_commands
+ (sb_devc *devc, struct ess_command *cmdtab[])
+{
+ struct ess_command *cmd;
+
+ cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ];
+
+ while (cmd->cmd != -1) {
+ ess_write (devc, cmd->cmd, cmd->data);
+ cmd++;
+ }
+}
+
+static void ess_change
+ (sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = ess_read (devc, reg);
+ value = (value & ~mask) | (val & mask);
+ ess_write (devc, reg, value);
+}
+
+static void ess_set_output_parms
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (devc->duplex) {
+ devc->trg_buf_16 = buf;
+ devc->trg_bytes_16 = nr_bytes;
+ devc->trg_intrflag_16 = intrflag;
+ devc->irq_mode_16 = IMODE_OUTPUT;
+ } else {
+ devc->trg_buf = buf;
+ devc->trg_bytes = nr_bytes;
+ devc->trg_intrflag = intrflag;
+ devc->irq_mode = IMODE_OUTPUT;
+ }
+}
+
+static void ess_set_input_parms
+ (int dev, unsigned long buf, int count, int intrflag)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ devc->trg_buf = buf;
+ devc->trg_bytes = count;
+ devc->trg_intrflag = intrflag;
+ devc->irq_mode = IMODE_INPUT;
+}
+
+static int ess_calc_div (int clock, int revert, int *speedp, int *diffp)
+{
+ int divider;
+ int speed, diff;
+ int retval;
+
+ speed = *speedp;
+ divider = (clock + speed / 2) / speed;
+ retval = revert - divider;
+ if (retval > revert - 1) {
+ retval = revert - 1;
+ divider = revert - retval;
+ }
+ /* This line is suggested. Must be wrong I think
+ *speedp = (clock + divider / 2) / divider;
+ So I chose the next one */
+
+ *speedp = clock / divider;
+ diff = speed - *speedp;
+ if (diff < 0) diff =-diff;
+ *diffp = diff;
+
+ return retval;
+}
+
+static int ess_calc_best_speed
+ (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
+{
+ int speed1 = *speedp, speed2 = *speedp;
+ int div1, div2;
+ int diff1, diff2;
+ int retval;
+
+ div1 = ess_calc_div (clock1, rev1, &speed1, &diff1);
+ div2 = ess_calc_div (clock2, rev2, &speed2, &diff2);
+
+ if (diff1 < diff2) {
+ *divp = div1;
+ *speedp = speed1;
+ retval = 1;
+ } else {
+ *divp = div2;
+ *speedp = speed2;
+ retval = 2;
+ }
+
+ return retval;
+}
+
+/*
+ * Depending on the audiochannel ESS devices can
+ * have different clock settings. These are made consistent for duplex
+ * however.
+ * callers of ess_speed only do an audionum suggestion, which means
+ * input suggests 1, output suggests 2. This suggestion is only true
+ * however when doing duplex.
+ */
+static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
+{
+ int diff = 0, div, choice;
+
+ if (devc->duplex) {
+ /*
+ * The 0x80 is important for the first audio channel
+ */
+ div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
+ } else {
+ choice = ess_calc_best_speed (397700, 128, 795500, 256, &div, speedp);
+ if (choice == 2) div |= 0x80;
+ }
+ *divp = div;
+}
+
+static void ess_speed (sb_devc *devc, int audionum)
+{
+ int speed;
+ int div, div2;
+
+ ess_common_speed (devc, &(devc->speed), &div);
+
+#ifdef FKS_REG_LOGGING
+printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, devc->speed, div);
+#endif
+
+ /* Set filter roll-off to 90% of speed/2 */
+ speed = (devc->speed * 9) / 20;
+
+ div2 = 256 - 7160000 / (speed * 82);
+
+ if (!devc->duplex) audionum = 1;
+
+ if (audionum == 1) {
+ /* Change behaviour of register A1 *
+ sb_chg_mixer(devc, 0x71, 0x20, 0x20)
+ * For ES1869 only??? */
+ ess_write (devc, 0xa1, div);
+ ess_write (devc, 0xa2, div2);
+ } else {
+ ess_setmixer (devc, 0x70, div);
+ /*
+ * FKS: fascinating: 0x72 doesn't seem to work.
+ */
+ ess_write (devc, 0xa2, div2);
+ ess_setmixer (devc, 0x72, div2);
+ }
+}
+
+#if 0
+static void ess_speed(sb_devc * devc)
+{
+ int divider;
+ unsigned char bits = 0;
+ int speed = devc->speed;
+
+ if (speed < 4000)
+ speed = 4000;
+ else if (speed > 48000)
+ speed = 48000;
+
+ if (speed > 22000)
+ {
+ bits = 0x80;
+ divider = 256 - (795500 + speed / 2) / speed;
+ }
+ else
+ {
+ divider = 128 - (397700 + speed / 2) / speed;
+ }
+
+ bits |= (unsigned char) divider;
+
+ ess_write (devc, 0xa1, bits);
+
+ /*
+ * Set filter divider register
+ */
+
+ speed = (speed * 9) / 20; /* Set filter roll-off to 90% of speed/2 */
+ divider = 256 - 7160000 / (speed * 82);
+
+ ess_write (devc, 0xa2, divider);
+
+ return;
+}
+#endif
+
+static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ ess_speed(devc, 1);
+
+ sb_dsp_command(devc, DSP_CMD_SPKOFF);
+
+ ess_write (devc, 0xb8, 0x0e); /* Auto init DMA mode */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
+ ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */
+
+ ess_exec_commands (devc, ess_inp_cmds);
+
+ ess_change (devc, 0xb1, 0xf0, 0x50);
+ ess_change (devc, 0xb2, 0xf0, 0x50);
+
+ devc->trigger_bits = 0;
+ return 0;
+}
+
+static int ess_audio_prepare_for_output_audio1 (int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ sb_dsp_reset(devc);
+ ess_speed(devc, 1);
+ ess_write (devc, 0xb8, 4); /* Auto init DMA mode */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
+ ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/request) */
+
+ ess_exec_commands (devc, ess_out_cmds);
+
+ ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable DMA */
+ ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable IRQ */
+
+ sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */
+
+ devc->trigger_bits = 0;
+ return 0;
+}
+
+static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+ unsigned char bits;
+
+/* FKS: qqq
+ sb_dsp_reset(devc);
+*/
+
+ /*
+ * Auto-Initialize:
+ * DMA mode + demand mode (8 bytes/request, yes I want it all!)
+ * But leave 16-bit DMA bit untouched!
+ */
+ ess_chgmixer (devc, 0x78, 0xd0, 0xd0);
+
+ ess_speed(devc, 2);
+
+ /* bits 4:3 on ES1887 represent recording source. Keep them! */
+ bits = ess_getmixer (devc, 0x7a) & 0x18;
+
+ /* Set stereo/mono */
+ if (devc->channels != 1) bits |= 0x02;
+
+ /* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */
+ if (devc->bits != AFMT_U8) bits |= 0x05; /* 16 bit */
+
+ /* Enable DMA, IRQ will be shared (hopefully)*/
+ bits |= 0x60;
+
+ ess_setmixer (devc, 0x7a, bits);
+
+ ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */
+
+ devc->trigger_bits = 0;
+ return 0;
+}
+
+static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "ess_audio_prepare_for_output: dma_out=%d,dma_in=%d\n"
+, audio_devs[dev]->dmap_out->dma, audio_devs[dev]->dmap_in->dma);
+#endif
+
+ if (devc->duplex) {
+ return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount);
+ } else {
+ return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount);
+ }
+}
+
+static void ess_audio_halt_xfer(int dev)
+{
+ unsigned long flags;
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ save_flags(flags);
+ cli();
+ sb_dsp_reset(devc);
+ restore_flags(flags);
+
+ /*
+ * Audio 2 may still be operational! Creates awful sounds!
+ */
+ if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00);
+}
+
+static void ess_audio_start_input
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ int count = nr_bytes;
+ sb_devc *devc = audio_devs[dev]->devc;
+ short c = -nr_bytes;
+
+ /*
+ * Start a DMA input to the buffer pointed by dmaqtail
+ */
+
+ if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1;
+ count--;
+
+ devc->irq_mode = IMODE_INPUT;
+
+ ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
+ ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+
+ ess_change (devc, 0xb8, 0x0f, 0x0f); /* Go */
+ devc->intr_active = 1;
+}
+
+static void ess_audio_output_block_audio1
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ int count = nr_bytes;
+ sb_devc *devc = audio_devs[dev]->devc;
+ short c = -nr_bytes;
+
+ if (audio_devs[dev]->dmap_out->dma > 3)
+ count >>= 1;
+ count--;
+
+ devc->irq_mode = IMODE_OUTPUT;
+
+ ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
+ ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+
+ ess_change (devc, 0xb8, 0x05, 0x05); /* Go */
+ devc->intr_active = 1;
+}
+
+static void ess_audio_output_block_audio2
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ int count = nr_bytes;
+ sb_devc *devc = audio_devs[dev]->devc;
+ short c = -nr_bytes;
+
+ if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1;
+ count--;
+
+ ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff));
+ ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff));
+ ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */
+
+ devc->irq_mode_16 = IMODE_OUTPUT;
+ devc->intr_active_16 = 1;
+}
+
+static void ess_audio_output_block
+ (int dev, unsigned long buf, int nr_bytes, int intrflag)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (devc->duplex) {
+ ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag);
+ } else {
+ ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag);
+ }
+}
+
+/*
+ * FKS: the if-statements for both bits and bits_16 are quite alike.
+ * Combine this...
+ */
+static void ess_audio_trigger(int dev, int bits)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ int bits_16 = bits & devc->irq_mode_16;
+ bits &= devc->irq_mode;
+
+ if (!bits && !bits_16) {
+ /* FKS oh oh.... wrong?? for dma 16? */
+ sb_dsp_command(devc, 0xd0); /* Halt DMA */
+ }
+
+ if (bits) {
+ switch (devc->irq_mode)
+ {
+ case IMODE_INPUT:
+ ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes,
+ devc->trg_intrflag);
+ break;
+
+ case IMODE_OUTPUT:
+ ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes,
+ devc->trg_intrflag);
+ break;
+ }
+ }
+
+ if (bits_16) {
+ switch (devc->irq_mode_16) {
+ case IMODE_INPUT:
+ ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16,
+ devc->trg_intrflag_16);
+ break;
+
+ case IMODE_OUTPUT:
+ ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16,
+ devc->trg_intrflag_16);
+ break;
+ }
+ }
+
+ devc->trigger_bits = bits | bits_16;
+}
+
+static int ess_audio_set_speed(int dev, int speed)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+ int minspeed, maxspeed, dummydiv;
+
+ if (speed > 0) {
+ minspeed = (devc->duplex ? 6215 : 5000 );
+ maxspeed = (devc->duplex ? 44100 : 48000);
+ if (speed < minspeed) speed = minspeed;
+ if (speed > maxspeed) speed = maxspeed;
+
+ ess_common_speed (devc, &speed, &dummydiv);
+
+ devc->speed = speed;
+ }
+ return devc->speed;
+}
+
+/*
+ * FKS: This is a one-on-one copy of sb1_audio_set_bits
+ */
+static unsigned int ess_audio_set_bits(int dev, unsigned int bits)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (bits != 0) {
+ if (bits == AFMT_U8 || bits == AFMT_S16_LE) {
+ devc->bits = bits;
+ } else {
+ devc->bits = AFMT_U8;
+ }
+ }
+
+ return devc->bits;
+}
+
+/*
+ * FKS: This is a one-on-one copy of sbpro_audio_set_channels
+ * (*) Modified it!!
+ */
+static short ess_audio_set_channels(int dev, short channels)
+{
+ sb_devc *devc = audio_devs[dev]->devc;
+
+ if (channels == 1 || channels == 2) devc->channels = channels;
+
+ return devc->channels;
+}
+
+static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */
+{
+ sb_audio_open,
+ sb_audio_close,
+ ess_set_output_parms,
+ ess_set_input_parms,
+ NULL,
+ ess_audio_prepare_for_input,
+ ess_audio_prepare_for_output,
+ ess_audio_halt_xfer,
+ NULL, /* local_qlen */
+ NULL, /* copy_from_user */
+ NULL,
+ NULL,
+ ess_audio_trigger,
+ ess_audio_set_speed,
+ ess_audio_set_bits,
+ ess_audio_set_channels
+};
+
+/*
+ * ess_audio_init must be called from sb_audio_init
+ */
+struct audio_driver *ess_audio_init
+ (sb_devc *devc, int *audio_flags, int *format_mask)
+{
+ *audio_flags = DMA_AUTOMODE;
+ *format_mask |= AFMT_S16_LE;
+
+ if (devc->duplex) {
+ int tmp_dma;
+ /*
+ * sb_audio_init thinks dma8 is for playback and
+ * dma16 is for record. Not now! So swap them.
+ */
+ tmp_dma = devc->dma16;
+ devc->dma16 = devc->dma8;
+ devc->dma8 = tmp_dma;
+
+ *audio_flags |= DMA_DUPLEX;
+ }
+
+ return &ess_audio_driver;
+}
+
+/****************************************************************************
+ * *
+ * ESS common *
+ * *
+ ****************************************************************************/
+static void ess_handle_channel
+ (char *channel, int dev, int intr_active, unsigned char flag, int irq_mode)
+{
+ if (!intr_active || !flag) return;
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode);
+#endif
+ switch (irq_mode) {
+ case IMODE_OUTPUT:
+ DMAbuf_outputintr (dev, 1);
+ break;
+
+ case IMODE_INPUT:
+ DMAbuf_inputintr (dev);
+ break;
+
+ case IMODE_INIT:
+ break;
+
+ default:
+ /* printk(KERN_WARN "ESS: Unexpected interrupt\n"); */
+ }
+}
+
+/*
+ * FKS: TODO!!! Finish this!
+ *
+ * I think midi stuff uses uart401, without interrupts.
+ * So IMODE_MIDI isn't a value for devc->irq_mode.
+ */
+void ess_intr (sb_devc *devc)
+{
+ int status;
+ unsigned char src;
+
+ if (devc->submodel == SUBMDL_ES1887) {
+ src = ess_getmixer (devc, 0x7f) >> 4;
+ } else {
+ src = 0xff;
+ }
+
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: sbintr src=%x\n",(int)src);
+#endif
+ ess_handle_channel
+ ( "Audio 1"
+ , devc->dev, devc->intr_active , src & 0x01, devc->irq_mode );
+ ess_handle_channel
+ ( "Audio 2"
+ , devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16);
+ /*
+ * Acknowledge interrupts
+ */
+ if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) {
+ ess_chgmixer (devc, 0x7a, 0x80, 0x00);
+ }
+
+ if (src & 0x01) {
+ status = inb(DSP_DATA_AVAIL);
+ }
+}
+
+static void ess_extended (sb_devc * devc)
+{
+ /* Enable extended mode */
+
+ sb_dsp_command(devc, 0xc6);
+}
+
+static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data)
+{
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: write reg %x: %x\n", reg, data);
+#endif
+ /* Write a byte to an extended mode register of ES1688 */
+
+ if (!sb_dsp_command(devc, reg))
+ return 0;
+
+ return sb_dsp_command(devc, data);
+}
+
+static int ess_read (sb_devc * devc, unsigned char reg)
+{
+ /* Read a byte from an extended mode register of ES1688 */
+
+ /* Read register command */
+ if (!sb_dsp_command(devc, 0xc0)) return -1;
+
+ if (!sb_dsp_command(devc, reg )) return -1;
+
+ return sb_dsp_get_byte(devc);
+}
+
+int ess_dsp_reset(sb_devc * devc)
+{
+ int loopc;
+
+#ifdef FKS_REG_LOGGING
+printk(KERN_INFO "FKS: ess_dsp_reset 1\n");
+ess_show_mixerregs (devc);
+#endif
+
+ DEB(printk("Entered ess_dsp_reset()\n"));
+
+ outb(3, DSP_RESET); /* Reset FIFO too */
+
+ udelay(10);
+ outb(0, DSP_RESET);
+ udelay(30);
+
+ for (loopc = 0; loopc < 1000 && !(inb(DSP_DATA_AVAIL) & 0x80); loopc++);
+
+ if (inb(DSP_READ) != 0xAA) {
+ DDB(printk("sb: No response to RESET\n"));
+ return 0; /* Sorry */
+ }
+ ess_extended (devc);
+
+ DEB(printk("sb_dsp_reset() OK\n"));
+
+#ifdef FKS_LOGGING
+printk(KERN_INFO "FKS: dsp_reset 2\n");
+ess_show_mixerregs (devc);
+#endif
+
+ return 1;
+}
+
+static int ess_irq_bits (int irq)
+{
+ switch (irq) {
+ case 2:
+ case 9:
+ return 0;
+
+ case 5:
+ return 1;
+
+ case 7:
+ return 2;
+
+ case 10:
+ return 3;
+
+ default:
+ printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", irq);
+ return -1;
+ }
+}
+
+/*
+ * Set IRQ configuration register for all ESS models
+ */
+static int ess_common_set_irq_hw (sb_devc * devc)
+{
+ int irq_bits;
+
+ if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return 0;
+
+ if (!ess_write (devc, 0xb1, 0x50 | (irq_bits << 2))) {
+ printk(KERN_ERR "ES1688: Failed to write to IRQ config register\n");
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * I wanna use modern ES1887 mixer irq handling. Funny is the
+ * fact that my BIOS wants the same. But suppose someone's BIOS
+ * doesn't do this!
+ * This is independent of duplex. If there's a 1887 this will
+ * prevent it from going into 1888 mode.
+ */
+static void ess_es1887_set_irq_hw (sb_devc * devc)
+{
+ int irq_bits;
+
+ if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return;
+
+ ess_chgmixer (devc, 0x7f, 0x0f, 0x01 | ((irq_bits + 1) << 1));
+}
+
+static int ess_set_irq_hw (sb_devc * devc)
+{
+ if (devc->submodel == SUBMDL_ES1887) ess_es1887_set_irq_hw (devc);
+
+ return ess_common_set_irq_hw (devc);
+}
+
+static unsigned int ess_identify (sb_devc * devc)
+{
+ unsigned int val;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ val = inb(MIXER_DATA) << 8;
+ udelay(20);
+ val |= inb(MIXER_DATA);
+ udelay(20);
+ restore_flags(flags);
+
+ return val;
+}
+
+/*
+ * ESS technology describes a detection scheme in their docs. It involves
+ * fiddling with the bits in certain mixer registers. ess_probe is supposed
+ * to help.
+ *
+ * FKS: tracing shows ess_probe writes wrong value to 0x64. Bit 3 reads 1, but
+ * should be written 0 only. Check this.
+ */
+static int ess_probe (sb_devc * devc, int reg, int xorval)
+{
+ int val1, val2, val3;
+
+ val1 = ess_getmixer (devc, reg);
+ val2 = val1 ^ xorval;
+ ess_setmixer (devc, reg, val2);
+ val3 = ess_getmixer (devc, reg);
+ ess_setmixer (devc, reg, val1);
+
+ return (val2 == val3);
+}
+
+int ess_init(sb_devc * devc, struct address_info *hw_config)
+{
+ unsigned char cfg;
+ int ess_major = 0, ess_minor = 0;
+ int i;
+ static char name[100], modelname[10];
+
+ /*
+ * Try to detect ESS chips.
+ */
+
+ sb_dsp_command(devc, 0xe7); /* Return identification */
+
+ for (i = 1000; i; i--) {
+ if (inb(DSP_DATA_AVAIL) & 0x80) {
+ if (ess_major == 0) {
+ ess_major = inb(DSP_READ);
+ } else {
+ ess_minor = inb(DSP_READ);
+ break;
+ }
+ }
+ }
+
+ if (ess_major == 0) return 0;
+
+ if (ess_major == 0x48 && (ess_minor & 0xf0) == 0x80) {
+ sprintf(name, "ESS ES488 AudioDrive (rev %d)",
+ ess_minor & 0x0f);
+ hw_config->name = name;
+ devc->model = MDL_SBPRO;
+ return 1;
+ }
+
+ /*
+ * This the detection heuristic of ESS technology, though somewhat
+ * changed to actually make it work.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ * if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878 (ess_identify)
+ * if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887)
+ * if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
+ * This is the most BETA part of the software: Will the detection
+ * always work?
+ */
+ devc->model = MDL_ESS;
+ devc->submodel = ess_minor & 0x0f;
+
+ if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
+ char *chip = NULL;
+
+ if (esstype) {
+ int submodel = -1;
+
+ switch (esstype) {
+ case 688:
+ submodel = 0x00;
+ break;
+ case 1688:
+ submodel = 0x08;
+ break;
+ case 1868:
+ submodel = SUBMDL_ES1868;
+ break;
+ case 1869:
+ submodel = SUBMDL_ES1869;
+ break;
+ case 1788:
+ submodel = SUBMDL_ES1788;
+ break;
+ case 1887:
+ submodel = SUBMDL_ES1887;
+ break;
+ case 1888:
+ submodel = SUBMDL_ES1888;
+ break;
+ };
+ if (submodel != -1) {
+ devc->submodel = submodel;
+ sprintf (modelname, "ES%d", esstype);
+ chip = modelname;
+ };
+ };
+ if (chip == NULL && (ess_minor & 0x0f) < 8) {
+ chip = "ES688";
+ };
+
+ if (chip == NULL) {
+ int type;
+
+ type = ess_identify (devc);
+
+ switch (type) {
+ case 0x1868:
+ chip = "ES1868";
+ devc->submodel = SUBMDL_ES1868;
+ break;
+ case 0x1869:
+ chip = "ES1869";
+ devc->submodel = SUBMDL_ES1869;
+ break;
+ case 0x1878:
+ chip = "ES1878";
+ devc->submodel = SUBMDL_ES1878;
+ break;
+ };
+ };
+#if 0
+ /*
+ * this one failed:
+ * the probing of bit 4 is another thought: from ES1788 and up, all
+ * chips seem to have hardware volume control. Bit 4 is readonly to
+ * check if a hardware volume interrupt has fired.
+ * Cause ES688/ES1688 don't have this feature, bit 4 might be writeable
+ * for these chips.
+ */
+ if (chip == NULL && !ess_probe(devc, 0x64, (1 << 4))) {
+#endif
+ /*
+ * the probing of bit 2 is my idea. The ES1887 docs want me to probe
+ * bit 3. This results in ES1688 being detected as ES1788.
+ * Bit 2 is for "Enable HWV IRQE", but as ES(1)688 chips don't have
+ * HardWare Volume, I think they don't have this IRQE.
+ */
+ if (chip == NULL && ess_probe(devc, 0x64, (1 << 2))) {
+ if (ess_probe (devc, 0x70, 0x7f)) {
+ if (ess_probe (devc, 0x64, (1 << 5))) {
+ chip = "ES1887";
+ devc->submodel = SUBMDL_ES1887;
+ } else {
+ chip = "ES1888";
+ devc->submodel = SUBMDL_ES1888;
+ }
+ } else {
+ chip = "ES1788";
+ devc->submodel = SUBMDL_ES1788;
+ }
+ };
+ if (chip == NULL) {
+ chip = "ES1688";
+ };
+
+ sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f);
+ } else {
+ strcpy(name, "Jazz16");
+ }
+
+ hw_config->name = name;
+ /* FKS: sb_dsp_reset to enable extended mode???? */
+ sb_dsp_reset(devc); /* Turn on extended mode */
+
+ /*
+ * Enable joystick and OPL3
+ */
+ cfg = ess_getmixer (devc, 0x40);
+ ess_setmixer (devc, 0x40, cfg | 0x03);
+ if (devc->submodel >= 8) { /* ES1688 */
+ devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */
+ }
+ sb_dsp_reset (devc);
+
+ /*
+ * This is important! If it's not done, the IRQ probe in sb_dsp_init
+ * may fail.
+ */
+ return ess_set_irq_hw (devc);
+}
+
+static int ess_set_dma_hw(sb_devc * devc)
+{
+ unsigned char cfg, dma_bits = 0, dma16_bits;
+ int dma;
+
+#ifdef FKS_LOGGING
+printk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n"
+, devc->dma8, devc->dma16, devc->duplex);
+#endif
+
+ /*
+ * FKS: It seems as if this duplex flag isn't set yet. Check it.
+ */
+ dma = devc->dma8;
+
+ if (dma > 3 || dma < 0 || dma == 2) {
+ dma_bits = 0;
+ printk(KERN_ERR "ESS1688: Invalid DMA8 %d\n", dma);
+ return 0;
+ } else {
+ /* Extended mode DMA enable */
+ cfg = 0x50;
+
+ if (dma == 3) {
+ dma_bits = 3;
+ } else {
+ dma_bits = dma + 1;
+ }
+ }
+
+ if (!ess_write (devc, 0xb2, cfg | (dma_bits << 2))) {
+ printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n");
+ return 0;
+ }
+
+ if (devc->duplex) {
+ dma = devc->dma16;
+ dma16_bits = 0;
+
+ if (dma >= 0) {
+ switch (dma) {
+ case 0:
+ dma_bits = 0x04;
+ break;
+ case 1:
+ dma_bits = 0x05;
+ break;
+ case 3:
+ dma_bits = 0x06;
+ break;
+ case 5:
+ dma_bits = 0x07;
+ dma16_bits = 0x20;
+ break;
+ default:
+ printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma);
+ return 0;
+ };
+ ess_chgmixer (devc, 0x78, 0x20, dma16_bits);
+ ess_chgmixer (devc, 0x7d, 0x07, dma_bits);
+ }
+ }
+ return 1;
+}
+
+/*
+ * This one is called from sb_dsp_init.
+ *
+ * Return values:
+ * 0: Failed
+ * 1: Succeeded or doesn't apply (not SUBMDL_ES1887)
+ */
+int ess_dsp_init (sb_devc *devc, struct address_info *hw_config)
+{
+ /*
+ * This for ES1887 to run Full Duplex. Actually ES1888
+ * is allowed to do so too. I have no idea yet if this
+ * will work for ES1888 however.
+ *
+ * For SB16 having both dma8 and dma16 means enable
+ * Full Duplex. Let's try this for ES1887 too
+ *
+ */
+ if (devc->submodel == SUBMDL_ES1887) {
+ if (hw_config->dma2 != -1) {
+ devc->dma16 = hw_config->dma2;
+ }
+ /*
+ * devc->duplex initialization is put here, cause
+ * ess_set_dma_hw needs it.
+ */
+ if (devc->dma8 != devc->dma16 && devc->dma16 != -1) {
+ devc->duplex = 1;
+ }
+
+ if (!ess_set_dma_hw (devc)) {
+ free_irq(devc->irq, devc);
+ return 0;
+ }
+ return 1;
+ } else {
+ return -1;
+ }
+}
+
+/****************************************************************************
+ * *
+ * ESS mixer *
+ * *
+ ****************************************************************************/
+
+#define ES688_RECORDING_DEVICES \
+ ( SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD )
+#define ES688_MIXER_DEVICES \
+ ( SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE \
+ | SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_VOLUME \
+ | SOUND_MASK_LINE2 | SOUND_MASK_SPEAKER )
+
+#define ES1688_RECORDING_DEVICES \
+ ( ES688_RECORDING_DEVICES )
+#define ES1688_MIXER_DEVICES \
+ ( ES688_MIXER_DEVICES | SOUND_MASK_RECLEV )
+
+#define ES1887_RECORDING_DEVICES \
+ ( ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 | SOUND_MASK_SYNTH)
+#define ES1887_MIXER_DEVICES \
+ ( ES1688_MIXER_DEVICES )
+
+/*
+ * Mixer registers of ES1887
+ *
+ * These registers specifically take care of recording levels. To make the
+ * mapping from playback devices to recording devices every recording
+ * devices = playback device + ES_REC_MIXER_RECDIFF
+ */
+#define ES_REC_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1)
+#define ES_REC_MIXER_RECDIFF (ES_REC_MIXER_RECBASE - SOUND_MIXER_SYNTH)
+
+#define ES_REC_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECPCM (SOUND_MIXER_PCM + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE (SOUND_MIXER_LINE + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECMIC (SOUND_MIXER_MIC + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECCD (SOUND_MIXER_CD + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES_REC_MIXER_RECDIFF)
+#define ES_REC_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES_REC_MIXER_RECDIFF)
+
+static mixer_tab es688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * The ES1688 specifics... hopefully correct...
+ * - 6 bit master volume
+ * I was wrong, ES1888 docs say ES1688 didn't have it.
+ * - RECLEV control
+ * These may apply to ES688 too. I have no idea.
+ */
+static mixer_tab es1688_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+static mixer_tab es1688later_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * This one is for all ESS chips with a record mixer.
+ * It's not used (yet) however
+ */
+static mixer_tab es_rec_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+/*
+ * This one is for ES1887. It's little different from es_rec_mix: it
+ * has 0x7c for PCM playback level. This is because ES1887 uses
+ * Audio 2 for playback.
+ */
+static mixer_tab es1887_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x7c, 7, 4, 0x7c, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECSPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECMIC, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECCD, 0x6a, 7, 4, 0x6a, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECIMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECRECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
+MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+static int ess_has_rec_mixer (int submodel)
+{
+ switch (submodel) {
+ case SUBMDL_ES1887:
+ return 1;
+ default:
+ return 0;
+ };
+};
+
+#ifdef FKS_LOGGING
+static int ess_mixer_mon_regs[]
+ = { 0x70, 0x71, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7d, 0x7f
+ , 0xa1, 0xa2, 0xa4, 0xa5, 0xa8, 0xa9
+ , 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, 0xb7, 0xb9
+ , 0x00};
+
+static void ess_show_mixerregs (sb_devc *devc)
+{
+ int *mp = ess_mixer_mon_regs;
+
+return;
+
+ while (*mp != 0) {
+ printk (KERN_INFO "res (%x)=%x\n", *mp, (int)(ess_getmixer (devc, *mp)));
+ mp++;
+ }
+}
+#endif
+
+void ess_setmixer (sb_devc * devc, unsigned int port, unsigned int value)
+{
+ unsigned long flags;
+
+#ifdef FKS_LOGGING
+printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value);
+#endif
+
+ save_flags(flags);
+ cli();
+ if (port >= 0xa0) {
+ ess_write (devc, port, value);
+ } else {
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ outb(((unsigned char) (value & 0xff)), MIXER_DATA);
+ udelay(20);
+ };
+ restore_flags(flags);
+}
+
+unsigned int ess_getmixer (sb_devc * devc, unsigned int port)
+{
+ unsigned int val;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ if (port >= 0xa0) {
+ val = ess_read (devc, port);
+ } else {
+ outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
+
+ udelay(20);
+ val = inb(MIXER_DATA);
+ udelay(20);
+ }
+ restore_flags(flags);
+
+ return val;
+}
+
+static void ess_chgmixer
+ (sb_devc * devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = ess_getmixer (devc, reg);
+ value = (value & ~mask) | (val & mask);
+ ess_setmixer (devc, reg, value);
+}
+
+/*
+ * ess_mixer_init must be called from sb_mixer_init
+ */
+void ess_mixer_init (sb_devc * devc)
+{
+ devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
+
+ /*
+ * Take care of ES1887 specifics...
+ */
+ switch (devc->submodel) {
+ case SUBMDL_ES1887:
+ devc->supported_devices = ES1887_MIXER_DEVICES;
+ devc->supported_rec_devices = ES1887_RECORDING_DEVICES;
+#ifdef FKS_LOGGING
+printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex);
+#endif
+ if (devc->duplex) {
+ devc->iomap = &es1887_mix;
+ } else {
+ devc->iomap = &es_rec_mix;
+ }
+ break;
+ default:
+ if (devc->submodel < 8) {
+ devc->supported_devices = ES688_MIXER_DEVICES;
+ devc->supported_rec_devices = ES688_RECORDING_DEVICES;
+ devc->iomap = &es688_mix;
+ } else {
+ /*
+ * es1688 has 4 bits master vol.
+ * later chips have 6 bits (?)
+ */
+ devc->supported_devices = ES1688_MIXER_DEVICES;
+ devc->supported_rec_devices = ES1688_RECORDING_DEVICES;
+ if (devc->submodel < 0x10) {
+ devc->iomap = &es1688_mix;
+ } else {
+ devc->iomap = &es1688later_mix;
+ }
+ }
+ }
+}
+
+/*
+ * Changing playback levels at an ESS chip with record mixer means having to
+ * take care of recording levels of recorded inputs (devc->recmask) too!
+ */
+int ess_mixer_set(sb_devc *devc, int dev, int left, int right)
+{
+ if (ess_has_rec_mixer (devc->submodel) && (devc->recmask & (1 << dev))) {
+ sb_common_mixer_set (devc, dev + ES_REC_MIXER_RECDIFF, left, right);
+ }
+ return sb_common_mixer_set (devc, dev, left, right);
+}
+
+/*
+ * After a sb_dsp_reset extended register 0xb4 (RECLEV) is reset too. After
+ * sb_dsp_reset RECLEV has to be restored. This is where ess_mixer_reload
+ * helps.
+ */
+void ess_mixer_reload (sb_devc *devc, int dev)
+{
+ int left, right, value;
+
+ value = devc->levels[dev];
+ left = value & 0x000000ff;
+ right = (value & 0x0000ff00) >> 8;
+
+ sb_common_mixer_set(devc, dev, left, right);
+}
+
+int es_rec_set_recmask(sb_devc * devc, int mask)
+{
+ int i, i_mask, cur_mask, diff_mask;
+ int value, left, right;
+
+#ifdef FKS_LOGGING
+printk (KERN_INFO "FKS: es_rec_set_recmask mask = %x\n", mask);
+#endif
+ /*
+ * Changing the recmask on an ESS chip with recording mixer means:
+ * (1) Find the differences
+ * (2) For "turned-on" inputs: make the recording level the playback level
+ * (3) For "turned-off" inputs: make the recording level zero
+ */
+ cur_mask = devc->recmask;
+ diff_mask = (cur_mask ^ mask);
+
+ for (i = 0; i < 32; i++) {
+ i_mask = (1 << i);
+ if (diff_mask & i_mask) { /* Difference? (1) */
+ if (mask & i_mask) { /* Turn it on (2) */
+ value = devc->levels[i];
+ left = value & 0x000000ff;
+ right = (value & 0x0000ff00) >> 8;
+ } else { /* Turn it off (3) */
+ left = 0;
+ left = 0;
+ right = 0;
+ }
+ sb_common_mixer_set(devc, i + ES_REC_MIXER_RECDIFF, left, right);
+ }
+ }
+ return mask;
+}
+
+int ess_set_recmask(sb_devc * devc, int *mask)
+{
+ /* This applies to ESS chips with record mixers only! */
+
+ if (ess_has_rec_mixer (devc->submodel)) {
+ *mask = es_rec_set_recmask (devc, *mask);
+ return 1; /* Applied */
+ } else {
+ return 0; /* Not applied */
+ }
+}
+
+/*
+ * ess_mixer_reset must be called from sb_mixer_reset
+ */
+int ess_mixer_reset (sb_devc * devc)
+{
+ /*
+ * Separate actions for ESS chips with a record mixer:
+ */
+ if (ess_has_rec_mixer (devc->submodel)) {
+ switch (devc->submodel) {
+ case SUBMDL_ES1887:
+ /*
+ * Separate actions for ES1887:
+ * Change registers 7a and 1c to make the record mixer the
+ * actual recording source.
+ */
+ ess_chgmixer(devc, 0x7a, 0x18, 0x08);
+ ess_chgmixer(devc, 0x1c, 0x07, 0x07);
+ break;
+ };
+ /*
+ * Call set_recmask for proper initialization
+ */
+ devc->recmask = devc->supported_rec_devices;
+ es_rec_set_recmask(devc, 0);
+ devc->recmask = 0;
+
+ return 1; /* We took care of recmask. */
+ } else {
+ return 0; /* We didn't take care; caller do it */
+ }
+}
+
+/****************************************************************************
+ * *
+ * ESS midi *
+ * *
+ ****************************************************************************/
+
+/*
+ * FKS: IRQ may be shared. Hm. And if so? Then What?
+ */
+int ess_midi_init(sb_devc * devc, struct address_info *hw_config)
+{
+ unsigned char cfg, tmp;
+
+ cfg = ess_getmixer (devc, 0x40) & 0x03;
+
+ if (devc->submodel < 8) {
+ ess_setmixer (devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */
+ return 0; /* ES688 doesn't support MPU401 mode */
+ }
+ tmp = (hw_config->io_base & 0x0f0) >> 4;
+
+ if (tmp > 3) {
+ ess_setmixer (devc, 0x40, cfg);
+ return 0;
+ }
+ cfg |= tmp << 3;
+
+ tmp = 1; /* MPU enabled without interrupts */
+
+ /* May be shared: if so the value is -ve */
+
+ switch (abs(hw_config->irq)) {
+ case 9:
+ tmp = 0x4;
+ break;
+ case 5:
+ tmp = 0x5;
+ break;
+ case 7:
+ tmp = 0x6;
+ break;
+ case 10:
+ tmp = 0x7;
+ break;
+ default:
+ return 0;
+ }
+
+ cfg |= tmp << 5;
+ ess_setmixer (devc, 0x40, cfg | 0x03);
+
+ return 1;
+}
+
diff --git a/drivers/sound/sb_ess.h b/drivers/sound/sb_ess.h
new file mode 100644
index 000000000..38aa072e0
--- /dev/null
+++ b/drivers/sound/sb_ess.h
@@ -0,0 +1,34 @@
+/*
+ * Created: 9-Jan-1999 Rolf Fokkens
+ */
+
+extern void ess_intr
+ (sb_devc *devc);
+extern int ess_dsp_init
+ (sb_devc *devc, struct address_info *hw_config);
+
+extern struct audio_driver *ess_audio_init
+ (sb_devc *devc, int *audio_flags, int *format_mask);
+extern int ess_midi_init
+ (sb_devc *devc, struct address_info *hw_config);
+extern void ess_mixer_init
+ (sb_devc *devc);
+
+extern int ess_init
+ (sb_devc *devc, struct address_info *hw_config);
+extern int ess_dsp_reset
+ (sb_devc *devc);
+
+extern void ess_setmixer
+ (sb_devc *devc, unsigned int port, unsigned int value);
+extern unsigned int ess_getmixer
+ (sb_devc *devc, unsigned int port);
+extern int ess_mixer_set
+ (sb_devc *devc, int dev, int left, int right);
+extern int ess_mixer_reset
+ (sb_devc *devc);
+extern void ess_mixer_reload
+ (sb_devc * devc, int dev);
+extern int ess_set_recmask
+ (sb_devc *devc, int *mask);
+
diff --git a/drivers/sound/sb_mixer.c b/drivers/sound/sb_mixer.c
index aaab4907d..97ce1b39d 100644
--- a/drivers/sound/sb_mixer.c
+++ b/drivers/sound/sb_mixer.c
@@ -1,4 +1,3 @@
-
/*
* sound/sb_mixer.c
*
@@ -12,7 +11,8 @@
* for more info.
*
*
- * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
+ * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
+ * Rolf Fokkens (Dec 20 1998) : Moved ESS stuff into sb_ess.[ch]
*/
#include <linux/config.h>
@@ -24,14 +24,226 @@
#include "sb.h"
#include "sb_mixer.h"
+#include "sb_ess.h"
+
+#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
+
+/* Same as SB Pro, unless I find otherwise */
+#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+
+#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | SOUND_MASK_VOLUME)
+
+/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
+ * channel is the COVOX/DisneySoundSource emulation volume control
+ * on the mixer. It does NOT control speaker volume. Should have own
+ * mask eventually?
+ */
+#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
+ SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
+
+#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
+ SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+ SOUND_MASK_IMIX)
+
+/* These are the only devices that are working at the moment. Others could
+ * be added once they are identified and a method is found to control them.
+ */
+#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
+ SOUND_MASK_PCM | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_VOLUME)
+
+static mixer_tab sbpro_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+#ifdef __SGNXPRO__
+#if 0
+static mixer_tab sgnxpro_mix = { /* not used anywhere */
+MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
+};
+#endif
+#endif
+
+static mixer_tab sb16_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5),
+MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5),
+MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5),
+MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5),
+MIX_ENT(SOUND_MIXER_IMIX, 0x3c, 0, 1, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
+MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2)
+};
+
+static mixer_tab als007_mix =
+{
+MIX_ENT(SOUND_MIXER_VOLUME, 0x62, 7, 4, 0x62, 3, 4),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x66, 7, 4, 0x66, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x64, 7, 4, 0x64, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x6a, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_CD, 0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
+};
+
+
+/* SM_GAMES Master volume is lower and PCM & FM volumes
+ higher than with SB Pro. This improves the
+ sound quality */
+
+static int smg_default_levels[32] =
+{
+ 0x2020, /* Master Volume */
+ 0x4b4b, /* Bass */
+ 0x4b4b, /* Treble */
+ 0x6464, /* FM */
+ 0x6464, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x0000, /* Mic */
+ 0x4b4b, /* CD */
+ 0x4b4b, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x4040, /* Line1 */
+ 0x4040, /* Line2 */
+ 0x1515 /* Line3 */
+};
+
+static int sb_default_levels[32] =
+{
+ 0x5a5a, /* Master Volume */
+ 0x4b4b, /* Bass */
+ 0x4b4b, /* Treble */
+ 0x4b4b, /* FM */
+ 0x4b4b, /* PCM */
+ 0x4b4b, /* PC Speaker */
+ 0x4b4b, /* Ext Line */
+ 0x1010, /* Mic */
+ 0x4b4b, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x4b4b, /* SB PCM */
+ 0x4b4b, /* Recording level */
+ 0x4b4b, /* Input gain */
+ 0x4b4b, /* Output gain */
+ 0x4040, /* Line1 */
+ 0x4040, /* Line2 */
+ 0x1515 /* Line3 */
+};
+
+static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
+{
+ 0x00, /* SOUND_MIXER_VOLUME */
+ 0x00, /* SOUND_MIXER_BASS */
+ 0x00, /* SOUND_MIXER_TREBLE */
+ 0x40, /* SOUND_MIXER_SYNTH */
+ 0x00, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x10, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x04, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00 /* SOUND_MIXER_OGAIN */
+};
+
+static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
+{
+ 0x00, /* SOUND_MIXER_VOLUME */
+ 0x00, /* SOUND_MIXER_BASS */
+ 0x00, /* SOUND_MIXER_TREBLE */
+ 0x20, /* SOUND_MIXER_SYNTH */
+ 0x00, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x08, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x02, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00 /* SOUND_MIXER_OGAIN */
+};
+
+static char smw_mix_regs[] = /* Left mixer registers */
+{
+ 0x0b, /* SOUND_MIXER_VOLUME */
+ 0x0d, /* SOUND_MIXER_BASS */
+ 0x0d, /* SOUND_MIXER_TREBLE */
+ 0x05, /* SOUND_MIXER_SYNTH */
+ 0x09, /* SOUND_MIXER_PCM */
+ 0x00, /* SOUND_MIXER_SPEAKER */
+ 0x03, /* SOUND_MIXER_LINE */
+ 0x01, /* SOUND_MIXER_MIC */
+ 0x07, /* SOUND_MIXER_CD */
+ 0x00, /* SOUND_MIXER_IMIX */
+ 0x00, /* SOUND_MIXER_ALTPCM */
+ 0x00, /* SOUND_MIXER_RECLEV */
+ 0x00, /* SOUND_MIXER_IGAIN */
+ 0x00, /* SOUND_MIXER_OGAIN */
+ 0x00, /* SOUND_MIXER_LINE1 */
+ 0x00, /* SOUND_MIXER_LINE2 */
+ 0x00 /* SOUND_MIXER_LINE3 */
+};
+
static int sbmixnum = 1;
static void sb_mixer_reset(sb_devc * devc);
void sb_mixer_set_stereo(sb_devc * devc, int mode)
{
- sb_setmixer(devc, OUT_FILTER, ((sb_getmixer(devc, OUT_FILTER) & ~STEREO_DAC)
- | (mode ? STEREO_DAC : MONO_DAC)));
+ sb_chgmixer(devc, OUT_FILTER, STEREO_DAC, (mode ? STEREO_DAC : MONO_DAC));
}
static int detect_mixer(sb_devc * devc)
@@ -78,22 +290,47 @@ void smw_mixer_init(sb_devc * devc)
sb_mixer_reset(devc);
}
-static int smw_mixer_set(sb_devc * devc, int dev, int value)
+int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
{
- int left = value & 0x000000ff;
- int right = (value & 0x0000ff00) >> 8;
- int reg, val;
+ int regoffs;
+ unsigned char val;
- if (left > 100)
- left = 100;
- if (right > 100)
- right = 100;
+ regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
- if (dev > 31)
+ if (regoffs == 0)
return -EINVAL;
- if (!(devc->supported_devices & (1 << dev))) /* Not supported */
- return -EINVAL;
+ val = sb_getmixer(devc, regoffs);
+ change_bits(devc, &val, dev, LEFT_CHN, left);
+
+ if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /*
+ * Change register
+ */
+ {
+ sb_setmixer(devc, regoffs, val); /*
+ * Save the old one
+ */
+ regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
+
+ if (regoffs == 0)
+ return left | (left << 8); /*
+ * Just left channel present
+ */
+
+ val = sb_getmixer(devc, regoffs); /*
+ * Read the new one
+ */
+ }
+ change_bits(devc, &val, dev, RIGHT_CHN, right);
+
+ sb_setmixer(devc, regoffs, val);
+
+ return left | (right << 8);
+}
+
+static int smw_mixer_set(sb_devc * devc, int dev, int left, int right)
+{
+ int reg, val;
switch (dev)
{
@@ -133,12 +370,7 @@ static int sb_mixer_set(sb_devc * devc, int dev, int value)
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
-
- int regoffs;
- unsigned char val;
-
- if (devc->model == MDL_SMW)
- return smw_mixer_set(devc, dev, value);
+ int retval;
if (left > 100)
left = 100;
@@ -153,42 +385,25 @@ static int sb_mixer_set(sb_devc * devc, int dev, int value)
*/
return -EINVAL;
- regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
-
- if (regoffs == 0)
- return -EINVAL;
-
- val = sb_getmixer(devc, regoffs);
- change_bits(devc, &val, dev, LEFT_CHN, left);
-
- devc->levels[dev] = left | (left << 8);
-
- if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /*
- * Change register
- */
- {
- sb_setmixer(devc, regoffs, val); /*
- * Save the old one
- */
- regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
-
- if (regoffs == 0)
- return left | (left << 8); /*
- * Just left channel present
- */
-
- val = sb_getmixer(devc, regoffs); /*
- * Read the new one
- */
+ /* Differentiate depending on the chipsets */
+ switch (devc->model) {
+ case MDL_SMW:
+ retval = smw_mixer_set(devc, dev, left, right);
+ break;
+ case MDL_ESS:
+ retval = ess_mixer_set(devc, dev, left, right);
+ break;
+ default:
+ retval = sb_common_mixer_set(devc, dev, left, right);
}
- change_bits(devc, &val, dev, RIGHT_CHN, right);
-
- sb_setmixer(devc, regoffs, val);
+ if (retval >= 0) devc->levels[dev] = retval;
- devc->levels[dev] = left | (right << 8);
- return left | (right << 8);
+ return retval;
}
+/*
+ * set_recsrc doesn't apply to ES188x
+ */
static void set_recsrc(sb_devc * devc, int src)
{
sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7));
@@ -207,7 +422,9 @@ static int set_recmask(sb_devc * devc, int mask)
case MDL_ESS:
case MDL_JAZZ:
case MDL_SMW:
-
+ if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) {
+ break;
+ };
if (devmask != SOUND_MASK_MIC &&
devmask != SOUND_MASK_LINE &&
devmask != SOUND_MASK_CD)
@@ -435,7 +652,10 @@ static void sb_mixer_reset(sb_devc * devc)
for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
sb_mixer_set(devc, i, devc->levels[i]);
- set_recmask(devc, SOUND_MASK_MIC);
+
+ if (devc->model != MDL_ESS || !ess_mixer_reset (devc)) {
+ set_recmask(devc, SOUND_MASK_MIC);
+ };
}
int sb_mixer_init(sb_devc * devc)
@@ -463,10 +683,7 @@ int sb_mixer_init(sb_devc * devc)
break;
case MDL_ESS:
- devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
- devc->supported_devices = ES688_MIXER_DEVICES;
- devc->supported_rec_devices = ES688_RECORDING_DEVICES;
- devc->iomap = &es688_mix;
+ ess_mixer_init (devc);
break;
case MDL_SMW:
diff --git a/drivers/sound/sb_mixer.h b/drivers/sound/sb_mixer.h
index 7f61e6e0c..f8627ce6c 100644
--- a/drivers/sound/sb_mixer.h
+++ b/drivers/sound/sb_mixer.h
@@ -15,51 +15,19 @@
* Modified:
* Hunyue Yau Jan 6 1994
* Added defines for the Sound Galaxy NX Pro mixer.
- *
+ *
+ * Rolf Fokkens Dec 20 1998
+ * Added defines for some ES188x chips.
+ *
+ * Rolf Fokkens Dec 27 1998
+ * Moved static stuff to sb_mixer.c
+ *
*/
#include <linux/config.h>
#include "legacy.h"
#ifdef CONFIG_SBDSP
-#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
-
-/* Same as SB Pro, unless I find otherwise */
-#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-
-#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | SOUND_MASK_VOLUME)
-
-/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
- * channel is the COVOX/DisneySoundSource emulation volume control
- * on the mixer. It does NOT control speaker volume. Should have own
- * mask eventually?
- */
-#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
- SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
-
-#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
-
-#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
-
-#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
-
-#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
- SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
- SOUND_MASK_IMIX)
-
-/* These are the only devices that are working at the moment. Others could
- * be added once they are identified and a method is found to control them.
- */
-#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
- SOUND_MASK_PCM | SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_VOLUME)
/*
* Mixer registers
*
@@ -119,201 +87,6 @@
#define MIX_ENT(name, reg_l, bit_l, len_l, reg_r, bit_r, len_r) \
{{reg_l, bit_l, len_l}, {reg_r, bit_r, len_r}}
-#ifdef __SB_MIXER_C__
-static mixer_tab sbpro_mix = {
-MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
-MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
-MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
-MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
-MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0)
-};
-static mixer_tab es688_mix = {
-MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
-MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
-MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
-MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
-MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
-MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
-MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
-};
-
-#ifdef __SGNXPRO__
-#if 0
-static mixer_tab sgnxpro_mix = { /* not used anywhere */
-MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
-MIX_ENT(SOUND_MIXER_BASS, 0x46, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 0x26, 7, 4, 0x26, 3, 4),
-MIX_ENT(SOUND_MIXER_PCM, 0x04, 7, 4, 0x04, 3, 4),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0x42, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 0x2e, 7, 4, 0x2e, 3, 4),
-MIX_ENT(SOUND_MIXER_MIC, 0x0a, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_CD, 0x28, 7, 4, 0x28, 3, 4),
-MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
-};
-#endif
-#endif
-
-static mixer_tab sb16_mix = {
-MIX_ENT(SOUND_MIXER_VOLUME, 0x30, 7, 5, 0x31, 7, 5),
-MIX_ENT(SOUND_MIXER_BASS, 0x46, 7, 4, 0x47, 7, 4),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x44, 7, 4, 0x45, 7, 4),
-MIX_ENT(SOUND_MIXER_SYNTH, 0x34, 7, 5, 0x35, 7, 5),
-MIX_ENT(SOUND_MIXER_PCM, 0x32, 7, 5, 0x33, 7, 5),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0x3b, 7, 2, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 0x38, 7, 5, 0x39, 7, 5),
-MIX_ENT(SOUND_MIXER_MIC, 0x3a, 7, 5, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_CD, 0x36, 7, 5, 0x37, 7, 5),
-MIX_ENT(SOUND_MIXER_IMIX, 0x3c, 0, 1, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
-MIX_ENT(SOUND_MIXER_IGAIN, 0x3f, 7, 2, 0x40, 7, 2),
-MIX_ENT(SOUND_MIXER_OGAIN, 0x41, 7, 2, 0x42, 7, 2)
-};
-
-static mixer_tab als007_mix =
-{
-MIX_ENT(SOUND_MIXER_VOLUME, 0x62, 7, 4, 0x62, 3, 4),
-MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_SYNTH, 0x66, 7, 4, 0x66, 3, 4),
-MIX_ENT(SOUND_MIXER_PCM, 0x64, 7, 4, 0x64, 3, 4),
-MIX_ENT(SOUND_MIXER_SPEAKER, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_LINE, 0x6e, 7, 4, 0x6e, 3, 4),
-MIX_ENT(SOUND_MIXER_MIC, 0x6a, 2, 3, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_CD, 0x68, 7, 4, 0x68, 3, 4),
-MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_RECLEV, 0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
-MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0)
-};
-
-
-/* SM_GAMES Master volume is lower and PCM & FM volumes
- higher than with SB Pro. This improves the
- sound quality */
-
-static int smg_default_levels[32] =
-{
- 0x2020, /* Master Volume */
- 0x4b4b, /* Bass */
- 0x4b4b, /* Treble */
- 0x6464, /* FM */
- 0x6464, /* PCM */
- 0x4b4b, /* PC Speaker */
- 0x4b4b, /* Ext Line */
- 0x0000, /* Mic */
- 0x4b4b, /* CD */
- 0x4b4b, /* Recording monitor */
- 0x4b4b, /* SB PCM */
- 0x4b4b, /* Recording level */
- 0x4b4b, /* Input gain */
- 0x4b4b, /* Output gain */
- 0x4040, /* Line1 */
- 0x4040, /* Line2 */
- 0x1515 /* Line3 */
-};
-
-static int sb_default_levels[32] =
-{
- 0x5a5a, /* Master Volume */
- 0x4b4b, /* Bass */
- 0x4b4b, /* Treble */
- 0x4b4b, /* FM */
- 0x4b4b, /* PCM */
- 0x4b4b, /* PC Speaker */
- 0x4b4b, /* Ext Line */
- 0x1010, /* Mic */
- 0x4b4b, /* CD */
- 0x0000, /* Recording monitor */
- 0x4b4b, /* SB PCM */
- 0x4b4b, /* Recording level */
- 0x4b4b, /* Input gain */
- 0x4b4b, /* Output gain */
- 0x4040, /* Line1 */
- 0x4040, /* Line2 */
- 0x1515 /* Line3 */
-};
-
-static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
-{
- 0x00, /* SOUND_MIXER_VOLUME */
- 0x00, /* SOUND_MIXER_BASS */
- 0x00, /* SOUND_MIXER_TREBLE */
- 0x40, /* SOUND_MIXER_SYNTH */
- 0x00, /* SOUND_MIXER_PCM */
- 0x00, /* SOUND_MIXER_SPEAKER */
- 0x10, /* SOUND_MIXER_LINE */
- 0x01, /* SOUND_MIXER_MIC */
- 0x04, /* SOUND_MIXER_CD */
- 0x00, /* SOUND_MIXER_IMIX */
- 0x00, /* SOUND_MIXER_ALTPCM */
- 0x00, /* SOUND_MIXER_RECLEV */
- 0x00, /* SOUND_MIXER_IGAIN */
- 0x00 /* SOUND_MIXER_OGAIN */
-};
-
-static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
-{
- 0x00, /* SOUND_MIXER_VOLUME */
- 0x00, /* SOUND_MIXER_BASS */
- 0x00, /* SOUND_MIXER_TREBLE */
- 0x20, /* SOUND_MIXER_SYNTH */
- 0x00, /* SOUND_MIXER_PCM */
- 0x00, /* SOUND_MIXER_SPEAKER */
- 0x08, /* SOUND_MIXER_LINE */
- 0x01, /* SOUND_MIXER_MIC */
- 0x02, /* SOUND_MIXER_CD */
- 0x00, /* SOUND_MIXER_IMIX */
- 0x00, /* SOUND_MIXER_ALTPCM */
- 0x00, /* SOUND_MIXER_RECLEV */
- 0x00, /* SOUND_MIXER_IGAIN */
- 0x00 /* SOUND_MIXER_OGAIN */
-};
-
-static char smw_mix_regs[] = /* Left mixer registers */
-{
- 0x0b, /* SOUND_MIXER_VOLUME */
- 0x0d, /* SOUND_MIXER_BASS */
- 0x0d, /* SOUND_MIXER_TREBLE */
- 0x05, /* SOUND_MIXER_SYNTH */
- 0x09, /* SOUND_MIXER_PCM */
- 0x00, /* SOUND_MIXER_SPEAKER */
- 0x03, /* SOUND_MIXER_LINE */
- 0x01, /* SOUND_MIXER_MIC */
- 0x07, /* SOUND_MIXER_CD */
- 0x00, /* SOUND_MIXER_IMIX */
- 0x00, /* SOUND_MIXER_ALTPCM */
- 0x00, /* SOUND_MIXER_RECLEV */
- 0x00, /* SOUND_MIXER_IGAIN */
- 0x00, /* SOUND_MIXER_OGAIN */
- 0x00, /* SOUND_MIXER_LINE1 */
- 0x00, /* SOUND_MIXER_LINE2 */
- 0x00 /* SOUND_MIXER_LINE3 */
-};
-
/*
* Recording sources (SB Pro)
*/
@@ -332,4 +105,4 @@ static char smw_mix_regs[] = /* Left mixer registers */
#define ALS007_SYNTH 7
#endif
-#endif
+
diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c
index b5cb59cdf..44207cb62 100644
--- a/drivers/sound/sequencer.c
+++ b/drivers/sound/sequencer.c
@@ -16,9 +16,7 @@
*/
#include <linux/config.h>
-#ifdef CONFIG_KMOD
#include <linux/kmod.h>
-#endif
#define SEQUENCER_C
@@ -82,7 +80,7 @@ static volatile int iqhead = 0, iqtail = 0, iqlen = 0;
static volatile int seq_playing = 0;
static volatile int sequencer_busy = 0;
static int output_threshold;
-static int pre_event_timeout;
+static long pre_event_timeout;
static unsigned synth_open_mask;
static int seq_queue(unsigned char *note, char nonblock);
@@ -998,10 +996,8 @@ int sequencer_open(int dev, struct file *file)
if (dev) /* Patch manager device (obsolete) */
return -ENXIO;
-#ifdef CONFIG_KMOD
if(synth_devs[dev] == NULL)
request_module("synth0");
-#endif
if (mode == OPEN_READ)
{
diff --git a/drivers/sound/skeleton.c b/drivers/sound/skeleton.c
new file mode 100644
index 000000000..f011058a2
--- /dev/null
+++ b/drivers/sound/skeleton.c
@@ -0,0 +1,224 @@
+/*
+ * PCI sound skeleton example
+ *
+ * (c) 1998 Red Hat Software
+ *
+ * This software may be used and distributed according to the
+ * terms of the GNU Public License, incorporated herein by
+ * reference.
+ *
+ * This example is designed to be built in the linux/drivers/sound
+ * directory as part of a kernel build. The example is modular only
+ * drop me a note once you have a working modular driver and want
+ * to integrate it with the main code.
+ * -- Alan <alan@redhat.com>
+ *
+ * This is a first draft. Please report any errors, corrections or
+ * improvements to me.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+
+#include "sound_config.h"
+#include "soundmodule.h"
+
+/*
+ * Define our PCI vendor ID here
+ */
+
+#ifndef PCI_VENDOR_MYIDENT
+#define PCI_VENDOR_MYIDENT 0x125D
+
+/*
+ * PCI identity for the card.
+ */
+
+#define PCI_DEVICE_ID_MYIDENT_MYCARD1 0x1969
+#endif
+
+#define CARD_NAME "ExampleWave 3D Pro Ultra ThingyWotsit"
+
+#define MAX_CARDS 8
+
+/*
+ * Each address_info object holds the information about one of
+ * our card resources. In this case the MSS emulation of our
+ * ficticious card. Its used to manage and attach things.
+ */
+
+static struct address_info mss_data[MAX_CARDS];
+static int cards = 0;
+
+/*
+ * Install the actual card. This is an example
+ */
+
+static int mycard_install(struct pci_dev *pcidev)
+{
+ int iobase;
+ int mssbase;
+ int mpubase;
+ u8 x;
+ u16 w;
+ u32 v;
+ int i;
+ int dma;
+
+ /*
+ * Our imaginary code has its I/O on PCI address 0, a
+ * MSS on PCI address 1 and an MPU on address 2
+ *
+ * For the example we will only initialise the MSS
+ */
+
+ iobase = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+ mssbase = pcidev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+ mpubase = pcidev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
+
+ /*
+ * Reset the board
+ */
+
+ /*
+ * Wait for completion. udelay() waits in microseconds
+ */
+
+ udelay(100);
+
+ /*
+ * Ok card ready. Begin setup proper. You might for example
+ * load the firmware here
+ */
+
+ dma = card_specific_magic(ioaddr);
+
+ /*
+ * Turn on legacy mode (example), There are also byte and
+ * dword (32bit) PCI configuration function calls
+ */
+
+ pci_read_config_word(pcidev, 0x40, &w);
+ w&=~(1<<15); /* legacy decode on */
+ w|=(1<<14); /* Reserved write as 1 in this case */
+ w|=(1<<3)|(1<<1)|(1<<0); /* SB on , FM on, MPU on */
+ pci_write_config_word(pcidev, 0x40, w);
+
+ /*
+ * Let the user know we found his toy.
+ */
+
+ printk(KERN_INFO "Programmed "CARD_NAME" at 0x%X to legacy mode.\n",
+ iobase);
+
+ /*
+ * Now set it up the description of the card
+ */
+
+ mss_data[cards].io_base = mssbase;
+ mss_data[cards].irq = pcidev->irq;
+ mss_data[cards].dma = dma;
+
+ /*
+ * Check there is an MSS present
+ */
+
+ if(ad1848_detect(mssbase, NULL, mss_data[cards].osp)==0)
+ return 0;
+
+ /*
+ * Initialize it
+ */
+
+ mss_data[cards].slots[3] = ad1848_init("MyCard MSS 16bit",
+ mssbase, mss_data[cards].irq);
+
+ cards++;
+ return 1;
+}
+
+
+/*
+ * This loop walks the PCI configuration database and finds where
+ * the sound cards are.
+ */
+
+int init_mycard(void)
+{
+ struct pci_dev *pcidev=NULL;
+ int count=0;
+
+ if(!pci_present())
+ return -ENODEV;
+
+
+ while((pcidev = pci_find_device(PCI_VENDOR_MYIDENT, PCI_DEVICE_ID_MYIDENT_MYCARD1, pcidev))!=NULL)
+ {
+ count+=mycard_install(pcidev);
+ if(count)
+ return 0;
+ if(count==MAX_CARDS)
+ break;
+ }
+
+ if(count==0)
+ return -ENODEV;
+ return 0;
+}
+
+/*
+ * This function is called when the user or kernel loads the
+ * module into memory.
+ */
+
+
+int init_module(void)
+{
+ if(init_mycard()<0)
+ {
+ printk(KERN_ERR "No "CARD_NAME" cards found.\n");
+ return -ENODEV;
+ }
+ /*
+ * Binds us to the sound subsystem
+ */
+ SOUND_LOCK;
+ return 0;
+}
+
+/*
+ * This is called when it is removed. It will only be removed
+ * when its use count is 0. For sound the SOUND_LOCK/SOUND_UNLOCK
+ * macros hide the entire work for this.
+ */
+
+void cleanup_module(void)
+{
+ for(i=0;i< cards; i++)
+ {
+ /*
+ * Free attached resources
+ */
+
+ ad1848_unload(mss_data[i].io_base,
+ mss_data[i].irq,
+ mss_data[i].dma,
+ mss_data[i].dma,
+ 0);
+ /*
+ * And disconnect the device from the kernel
+ */
+ sound_unload_audiodevice(mss_data[i].slots[3]);
+ }
+ /*
+ * Final clean up with the sound layer
+ */
+ SOUND_LOCK_END;
+}
+
diff --git a/drivers/sound/softoss_rs.c b/drivers/sound/softoss_rs.c
index ac9714ff5..2fa95f748 100644
--- a/drivers/sound/softoss_rs.c
+++ b/drivers/sound/softoss_rs.c
@@ -49,7 +49,7 @@ void softsynth_resample_loop(short *buf, int loops)
#endif
/* Interpolation (resolution of 512 steps) */
{
- int fract = v->ptr & 0x1f; /* 9 bits */
+ int fract = v->ptr & 0x1ff; /* 9 bits */
/* This method works with less arithmetic operations */
register int v1 = v->wave[ix];
diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c
index b57cd186a..b1899e143 100644
--- a/drivers/sound/sonicvibes.c
+++ b/drivers/sound/sonicvibes.c
@@ -47,6 +47,10 @@
* Now mixer behaviour can basically be selected between
* "OSS documented" and "OSS actual" behaviour
* 31.08.98 0.7 Fix realplayer problems - dac.count issues
+ * 10.12.98 0.8 Fix drain_dac trying to wait on not yet initialized DMA
+ * 16.12.98 0.9 Fix a few f_file & FMODE_ bugs
+ * 06.01.99 0.10 remove the silly SA_INTERRUPT flag.
+ * hopefully killed the egcs section type conflict
*
*/
@@ -763,17 +767,14 @@ static void sv_update_ptr(struct sv_state *s)
s->dma_adc.hwptr = hwptr;
s->dma_adc.total_bytes += diff;
s->dma_adc.count += diff;
- if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- wake_up(&s->dma_adc.wait);
- } else {
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+ wake_up(&s->dma_adc.wait);
+ if (!s->dma_adc.mapped) {
if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
s->enable &= ~SV_CENABLE_RE;
wrindir(s, SV_CIENABLE, s->enable);
s->dma_adc.error++;
}
- if (s->dma_adc.count > 0)
- wake_up(&s->dma_adc.wait);
}
}
/* update DAC pointer */
@@ -796,7 +797,7 @@ static void sv_update_ptr(struct sv_state *s)
clear_advance(s);
s->dma_dac.endcleared = 1;
}
- if (s->dma_dac.count < (signed)s->dma_dac.dmasize)
+ if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize)
wake_up(&s->dma_dac.wait);
}
}
@@ -1226,7 +1227,7 @@ static int drain_dac(struct sv_state *s, int nonblock)
unsigned long flags;
int count, tmo;
- if (s->dma_dac.mapped)
+ if (s->dma_dac.mapped || !s->dma_dac.ready)
return 0;
current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&s->dma_dac.wait, &wait);
@@ -1381,27 +1382,22 @@ static unsigned int sv_poll(struct file *file, struct poll_table_struct *wait)
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_flags & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE)
poll_wait(file, &s->dma_dac.wait, wait);
- if (file->f_flags & FMODE_READ)
+ if (file->f_mode & FMODE_READ)
poll_wait(file, &s->dma_adc.wait, wait);
spin_lock_irqsave(&s->lock, flags);
sv_update_ptr(s);
- if (file->f_flags & FMODE_READ) {
- if (s->dma_adc.mapped) {
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- mask |= POLLIN | POLLRDNORM;
- } else {
- if (s->dma_adc.count > 0)
- mask |= POLLIN | POLLRDNORM;
- }
+ if (file->f_mode & FMODE_READ) {
+ if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+ mask |= POLLIN | POLLRDNORM;
}
- if (file->f_flags & FMODE_WRITE) {
+ if (file->f_mode & FMODE_WRITE) {
if (s->dma_dac.mapped) {
if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
mask |= POLLOUT | POLLWRNORM;
} else {
- if ((signed)s->dma_dac.dmasize > s->dma_dac.count)
+ if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)
mask |= POLLOUT | POLLWRNORM;
}
}
@@ -1785,11 +1781,11 @@ static int sv_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE)
drain_dac(s, file->f_flags & O_NONBLOCK);
down(&s->open_sem);
- if (file->f_flags & FMODE_WRITE) {
+ if (file->f_mode & FMODE_WRITE) {
stop_dac(s);
dealloc_dmabuf(&s->dma_dac);
}
- if (file->f_flags & FMODE_READ) {
+ if (file->f_mode & FMODE_READ) {
stop_adc(s);
dealloc_dmabuf(&s->dma_adc);
}
@@ -1922,16 +1918,16 @@ static unsigned int sv_midi_poll(struct file *file, struct poll_table_struct *wa
unsigned int mask = 0;
VALIDATE_STATE(s);
- if (file->f_flags & FMODE_WRITE)
+ if (file->f_mode & FMODE_WRITE)
poll_wait(file, &s->midi.owait, wait);
- if (file->f_flags & FMODE_READ)
+ if (file->f_mode & FMODE_READ)
poll_wait(file, &s->midi.iwait, wait);
spin_lock_irqsave(&s->lock, flags);
- if (file->f_flags & FMODE_READ) {
+ if (file->f_mode & FMODE_READ) {
if (s->midi.icnt > 0)
mask |= POLLIN | POLLRDNORM;
}
- if (file->f_flags & FMODE_WRITE) {
+ if (file->f_mode & FMODE_WRITE) {
if (s->midi.ocnt < MIDIOUTBUF)
mask |= POLLOUT | POLLWRNORM;
}
@@ -2249,7 +2245,7 @@ static unsigned dmaio = 0xac00;
/* --------------------------------------------------------------------- */
-static const struct initvol {
+static struct initvol {
int mixch;
int vol;
} initvol[] __initdata = {
@@ -2277,7 +2273,7 @@ __initfunc(int init_sonicvibes(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "sv: version v0.7 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.10 time " __TIME__ " " __DATE__ "\n");
#if 0
if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2388,18 +2384,18 @@ __initfunc(int init_sonicvibes(void))
wrindir(s, SV_CIPCMSR1, ((8000 * 65536 / FULLRATE) >> 8) & 0xff);
wrindir(s, SV_CIADCOUTPUT, 0);
/* request irq */
- if (request_irq(s->irq, sv_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", s)) {
+ if (request_irq(s->irq, sv_interrupt, SA_SHIRQ, "S3 SonicVibes", s)) {
printk(KERN_ERR "sv: irq %u in use\n", s->irq);
goto err_irq;
}
printk(KERN_INFO "sv: found adapter at io %#06x irq %u dmaa %#06x dmac %#06x revision %u\n",
s->ioenh, s->irq, s->iodmaa, s->iodmac, rdindir(s, SV_CIREVISION));
/* register devices */
- if ((s->dev_audio = register_sound_dsp(&sv_audio_fops)) < 0)
+ if ((s->dev_audio = register_sound_dsp(&sv_audio_fops, -1)) < 0)
goto err_dev1;
- if ((s->dev_mixer = register_sound_mixer(&sv_mixer_fops)) < 0)
+ if ((s->dev_mixer = register_sound_mixer(&sv_mixer_fops, -1)) < 0)
goto err_dev2;
- if ((s->dev_midi = register_sound_midi(&sv_midi_fops)) < 0)
+ if ((s->dev_midi = register_sound_midi(&sv_midi_fops, -1)) < 0)
goto err_dev3;
if ((s->dev_dmfm = register_sound_special(&sv_dmfm_fops, 15 /* ?? */)) < 0)
goto err_dev4;
diff --git a/drivers/sound/sound_calls.h b/drivers/sound/sound_calls.h
index 8c91cb72d..e162d8edc 100644
--- a/drivers/sound/sound_calls.h
+++ b/drivers/sound/sound_calls.h
@@ -205,6 +205,11 @@ void attach_sscape (struct address_info *hw_config);
int probe_ss_ms_sound (struct address_info *hw_config);
void attach_ss_ms_sound(struct address_info * hw_config);
+/* From ad1816.c */
+void unload_ad1816(struct address_info *hw_info);
+int probe_ad1816 (struct address_info *hw_config);
+void attach_ad1816 (struct address_info *hw_config);
+
/* From aedsp16.c */
int InitAEDSP16_SBPRO(struct address_info *hw_config);
int InitAEDSP16_MSS(struct address_info *hw_config);
@@ -281,29 +286,10 @@ void attach_vidc(struct address_info *hw_config);
int probe_vidc(struct address_info *hw_config);
void unload_vidc(struct address_info *hw_config);
-/* From wavefront.c */
-void attach_wavefront (struct address_info *hw_config);
-int probe_wavefront (struct address_info *hw_config);
-void unload_wavefront (struct address_info *hw_config);
-
-/* From wf_midi.c */
-void attach_wf_mpu(struct address_info * hw_config);
-int probe_wf_mpu(struct address_info *hw_config);
-void unload_wf_mpu(struct address_info *hw_config);
-int virtual_midi_enable (int mididev, struct address_info *);
-void virtual_midi_disable (int mididev);
-
-/* From wavefront.c */
-void attach_wavefront (struct address_info *hw_config);
-int probe_wavefront (struct address_info *hw_config);
-void unload_wavefront (struct address_info *hw_config);
-
-/* From wf_midi.c */
-void attach_wf_mpu(struct address_info * hw_config);
-int probe_wf_mpu(struct address_info *hw_config);
-void unload_wf_mpu(struct address_info *hw_config);
-int virtual_midi_enable (int mididev, struct address_info *);
-void virtual_midi_disable (int mididev);
+/* From waveartist.c */
+void attach_waveartist(struct address_info *hw_config);
+int probe_waveartist(struct address_info *hw_config);
+void unload_waveartist(struct address_info *hw_config);
/* From wavefront.c */
void attach_wavefront (struct address_info *hw_config);
@@ -314,5 +300,5 @@ void unload_wavefront (struct address_info *hw_config);
void attach_wf_mpu(struct address_info * hw_config);
int probe_wf_mpu(struct address_info *hw_config);
void unload_wf_mpu(struct address_info *hw_config);
-int virtual_midi_enable (int mididev, struct address_info *);
-void virtual_midi_disable (int mididev);
+int virtual_midi_enable (void);
+int virtual_midi_disable (void);
diff --git a/drivers/sound/sound_config.h b/drivers/sound/sound_config.h
index 805de62dc..18ff32e34 100644
--- a/drivers/sound/sound_config.h
+++ b/drivers/sound/sound_config.h
@@ -41,8 +41,6 @@
#define DSP_BUFFCOUNT 1 /* 1 is recommended. */
#endif
-#define DMA_AUTOINIT 0x10
-
#define FM_MONO 0x388 /* This is the I/O address used by AdLib */
#ifndef CONFIG_PAS_BASE
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index 360028421..95c332208 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -43,6 +43,7 @@
#include <linux/fs.h>
#include <linux/sound.h>
#include <linux/major.h>
+#include <linux/kmod.h>
struct sound_unit
@@ -57,24 +58,32 @@ struct sound_unit
* join into it. Called with the lock asserted
*/
-static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int low, int top)
+static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list, struct file_operations *fops, int index, int low, int top)
{
int n=low;
- while(n<top)
- {
- /* Found a hole ? */
- if(*list==NULL || (*list)->unit_minor>n)
- break;
- list=&((*list)->next);
- n+=16;
- }
-
- if(n==top)
- {
- return -1;
- }
-
+ if (index < 0) { /* first free */
+ while(n<top)
+ {
+ /* Found a hole ? */
+ if(*list==NULL || (*list)->unit_minor>n)
+ break;
+ list=&((*list)->next);
+ n+=16;
+ }
+
+ if(n>=top)
+ return -ENOMEM;
+ } else {
+ n = low+(index*16);
+ while (*list) {
+ if ((*list)->unit_minor==n)
+ return -EBUSY;
+ if ((*list)->unit_minor>n)
+ break;
+ list=&((*list)->next);
+ }
+ }
/*
* Fill it in
@@ -127,7 +136,7 @@ static spinlock_t sound_loader_lock = SPIN_LOCK_UNLOCKED;
* list. Acquires locks as needed
*/
-static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int low, int top)
+static int sound_insert_unit(struct sound_unit **list, struct file_operations *fops, int index, int low, int top)
{
int r;
struct sound_unit *s=(struct sound_unit *)kmalloc(sizeof(struct sound_unit), GFP_KERNEL);
@@ -135,7 +144,7 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
return -1;
spin_lock(&sound_loader_lock);
- r=__sound_insert_unit(s,list,fops,low,top);
+ r=__sound_insert_unit(s,list,fops,index,low,top);
spin_unlock(&sound_loader_lock);
if(r==-1)
@@ -181,21 +190,21 @@ static struct sound_unit *chains[16];
int register_sound_special(struct file_operations *fops, int unit)
{
- return sound_insert_unit(&chains[unit&15], fops, unit, unit+1);
+ return sound_insert_unit(&chains[unit&15], fops, -1, unit, unit+1);
}
EXPORT_SYMBOL(register_sound_special);
-int register_sound_mixer(struct file_operations *fops)
+int register_sound_mixer(struct file_operations *fops, int dev)
{
- return sound_insert_unit(&chains[0], fops, 0, 128);
+ return sound_insert_unit(&chains[0], fops, dev, 0, 128);
}
EXPORT_SYMBOL(register_sound_mixer);
-int register_sound_midi(struct file_operations *fops)
+int register_sound_midi(struct file_operations *fops, int dev)
{
- return sound_insert_unit(&chains[2], fops, 2, 130);
+ return sound_insert_unit(&chains[2], fops, dev, 2, 130);
}
EXPORT_SYMBOL(register_sound_midi);
@@ -205,16 +214,16 @@ EXPORT_SYMBOL(register_sound_midi);
* in open - see below.
*/
-int register_sound_dsp(struct file_operations *fops)
+int register_sound_dsp(struct file_operations *fops, int dev)
{
- return sound_insert_unit(&chains[3], fops, 3, 131);
+ return sound_insert_unit(&chains[3], fops, dev, 3, 131);
}
EXPORT_SYMBOL(register_sound_dsp);
-int register_sound_synth(struct file_operations *fops)
+int register_sound_synth(struct file_operations *fops, int dev)
{
- return sound_insert_unit(&chains[9], fops, 9, 137);
+ return sound_insert_unit(&chains[9], fops, dev, 9, 137);
}
EXPORT_SYMBOL(register_sound_synth);
@@ -279,6 +288,20 @@ static struct file_operations soundcore_fops=
NULL
};
+static struct sound_unit *__look_for_unit(int chain, int unit)
+{
+ struct sound_unit *s;
+
+ s=chains[chain];
+ while(s && s->unit_minor <= unit)
+ {
+ if(s->unit_minor==unit)
+ return s;
+ s=s->next;
+ }
+ return NULL;
+}
+
int soundcore_open(struct inode *inode, struct file *file)
{
int chain;
@@ -294,28 +317,45 @@ int soundcore_open(struct inode *inode, struct file *file)
}
spin_lock(&sound_loader_lock);
+ s = __look_for_unit(chain, unit);
+ if (s == NULL) {
+ char mod[32];
- s=chains[chain];
-
- while(s && s->unit_minor <= unit)
- {
- if(s->unit_minor==unit)
- {
- file->f_op=s->unit_fops;
- spin_unlock(&sound_loader_lock);
- if(file->f_op->open)
- return file->f_op->open(inode,file);
- else
- return 0;
- break;
- }
- s=s->next;
+ spin_unlock(&sound_loader_lock);
+ /*
+ * Please, don't change this order or code.
+ * For ALSA slot means soundcard and OSS emulation code
+ * comes as add-on modules which aren't depend on
+ * ALSA toplevel modules for soundcards, thus we need
+ * load them at first. [Jaroslav Kysela <perex@jcu.cz>]
+ */
+ sprintf(mod, "sound-slot-%i", unit>>4);
+ request_module(mod);
+ sprintf(mod, "sound-service-%i-%i", unit>>4, chain);
+ request_module(mod);
+ spin_lock(&sound_loader_lock);
+ s = __look_for_unit(chain, unit);
+ }
+ if (s) {
+ file->f_op=s->unit_fops;
+ spin_unlock(&sound_loader_lock);
+ if(file->f_op->open)
+ return file->f_op->open(inode,file);
+ else
+ return 0;
}
spin_unlock(&sound_loader_lock);
return -ENODEV;
}
+extern int mod_firmware_load(const char *, char **);
+EXPORT_SYMBOL(mod_firmware_load);
+
#ifdef MODULE
+
+MODULE_DESCRIPTION("Core sound module");
+MODULE_AUTHOR("Alan Cox");
+
void cleanup_module(void)
{
/* We have nothing to really do here - we know the lists must be
diff --git a/drivers/sound/sound_firmware.c b/drivers/sound/sound_firmware.c
index f4777addf..c446e98e0 100644
--- a/drivers/sound/sound_firmware.c
+++ b/drivers/sound/sound_firmware.c
@@ -58,4 +58,3 @@ int mod_firmware_load(const char *fn, char **fp)
return r;
}
-EXPORT_SYMBOL(mod_firmware_load);
diff --git a/drivers/sound/sound_syms.c b/drivers/sound/sound_syms.c
index 08f092e90..b0568d82a 100644
--- a/drivers/sound/sound_syms.c
+++ b/drivers/sound/sound_syms.c
@@ -43,6 +43,7 @@ EXPORT_SYMBOL(sound_unload_synthdev);
EXPORT_SYMBOL(load_mixer_volumes);
+
EXPORT_SYMBOL(conf_printf);
EXPORT_SYMBOL(conf_printf2);
@@ -54,5 +55,5 @@ EXPORT_SYMBOL(softoss_dev);
EXPORT_SYMBOL(sound_locker);
EXPORT_SYMBOL(sound_notifier_chain_register);
-MODULE_DESCRIPTION("Sound subsystem");
+MODULE_DESCRIPTION("OSS Sound subsystem");
MODULE_AUTHOR("Hannu Savolainen, et al.");
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index b830afdd2..cf3b70fea 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -456,13 +456,11 @@ static int sound_open(struct inode *inode, struct file *file)
case SND_DEV_CTL:
dev >>= 4;
-#ifdef CONFIG_KMOD
if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
char modname[20];
sprintf(modname, "mixer%d", dev);
request_module(modname);
}
-#endif
if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
return -ENXIO;
break;
@@ -578,14 +576,12 @@ static int sound_mixer_ioctl(int mixdev, unsigned int cmd, caddr_t arg)
{
if (mixdev < 0 || mixdev >= MAX_MIXER_DEV)
return -ENXIO;
-#ifdef CONFIG_KMOD
/* Try to load the mixer... */
if (mixer_devs[mixdev] == NULL) {
char modname[20];
sprintf(modname, "mixer%d", mixdev);
request_module(modname);
}
-#endif /* CONFIG_KMOD */
if (mixdev >= num_mixers || !mixer_devs[mixdev])
return -ENXIO;
if (cmd == SOUND_MIXER_INFO)
@@ -760,6 +756,9 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
dmap->mapping_flags |= DMA_MAP_MAPPED;
+ if( audio_devs[dev]->d->mmap)
+ audio_devs[dev]->d->mmap(dev);
+
memset(dmap->raw_buf,
dmap->neutral_byte,
dmap->bytes_in_use);
@@ -906,8 +905,10 @@ void cleanup_module(void)
{
return;
}
+#ifdef CONFIG_PROC_FS
if (proc_unregister(&proc_root, PROC_SOUND))
printk(KERN_ERR "sound: unregistering /proc/sound failed\n");
+#endif
if (chrdev_registered)
destroy_special_devices();
diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c
index 97113a838..1a6b79c76 100644
--- a/drivers/sound/trix.c
+++ b/drivers/sound/trix.c
@@ -26,6 +26,7 @@
#ifdef CONFIG_TRIX
#ifdef INCLUDE_TRIX_BOOT
+#include <linux/init.h>
#include "trix_boot.h"
#else
static unsigned char *trix_boot = NULL;
diff --git a/drivers/sound/vidc.c b/drivers/sound/vidc.c
index c33ed9beb..36a4eafb1 100644
--- a/drivers/sound/vidc.c
+++ b/drivers/sound/vidc.c
@@ -6,32 +6,50 @@
* Copyright (C) 1997 by Russell King <rmk@arm.uk.linux.org>
*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+
#include <asm/io.h>
#include <asm/dma.h>
#include "sound_config.h"
+#include "soundmodule.h"
#include "vidc.h"
int vidc_busy;
-void vidc_update_filler(int bits, int channels)
+void vidc_update_filler(int format, int channels)
{
- int filltype;
+ int fillertype;
+
+#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3))
- filltype = bits + channels;
- switch (filltype)
+ fillertype = TYPE(format, channels);
+printk("filler type: %X\n", fillertype);
+ switch (fillertype)
{
default:
- case 9:
- vidc_filler = vidc_fill_1x8;
+ case TYPE(AFMT_U8, 1):
+ vidc_filler = vidc_fill_1x8_u;
break;
- case 10:
- vidc_filler = vidc_fill_2x8;
+
+ case TYPE(AFMT_U8, 2):
+ vidc_filler = vidc_fill_2x8_u;
break;
- case 17:
- vidc_filler = vidc_fill_1x16;
+
+ case TYPE(AFMT_S8, 1):
+ vidc_filler = vidc_fill_1x8_s;
break;
- case 18:
- vidc_filler = vidc_fill_2x16;
+
+ case TYPE(AFMT_S8, 2):
+ vidc_filler = vidc_fill_2x8_s;
+ break;
+
+ case TYPE(AFMT_S16_LE, 1):
+ vidc_filler = vidc_fill_1x16_s;
+ break;
+
+ case TYPE(AFMT_S16_LE, 2):
+ vidc_filler = vidc_fill_2x16_s;
break;
}
}
@@ -55,12 +73,12 @@ void attach_vidc(struct address_info *hw_config)
printk(KERN_ERR "VIDCsound: can't allocate virtual DMA channel\n");
return;
}
- if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, "VIDCsound", NULL))
+ if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, "VIDCsound", &dma_start))
{
printk(KERN_ERR "VIDCsound: can't allocate DMA interrupt\n");
return;
}
- vidc_synth_init(hw_config);
+// vidc_synth_init(hw_config);
vidc_audio_init(hw_config);
vidc_mixer_init(hw_config);
}
@@ -76,6 +94,32 @@ int probe_vidc(struct address_info *hw_config)
void unload_vidc(struct address_info *hw_config)
{
+ int i;
+
free_irq(hw_config->irq, NULL);
sound_free_dma(hw_config->dma);
+
+ for (i = 0; i < 2; i++)
+ free_page(dma_buf[i]);
+}
+
+#ifdef MODULE
+static struct address_info config;
+
+int init_module(void)
+{
+ if (probe_vidc(&config) == 0)
+ return -ENODEV;
+ printk("VIDC 16-bit serial sound\n");
+ SOUND_LOCK;
+ attach_vidc(&config);
+ return 0;
}
+
+void cleanup_module(void)
+{
+ unload_vidc(&config);
+ SOUND_LOCK_END;
+}
+
+#endif
diff --git a/drivers/sound/vidc.h b/drivers/sound/vidc.h
index 33625f392..a79bdc85d 100644
--- a/drivers/sound/vidc.h
+++ b/drivers/sound/vidc.h
@@ -16,14 +16,18 @@ extern int vidc_busy;
* Filler routines for different channels and sample sizes
*/
-extern unsigned long vidc_fill_1x8(unsigned long ibuf, unsigned long iend,
- unsigned long obuf, int mask);
-extern unsigned long vidc_fill_2x8(unsigned long ibuf, unsigned long iend,
- unsigned long obuf, int mask);
-extern unsigned long vidc_fill_1x16(unsigned long ibuf, unsigned long iend,
- unsigned long obuf, int mask);
-extern unsigned long vidc_fill_2x16(unsigned long ibuf, unsigned long iend,
- unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x8_u(unsigned long ibuf, unsigned long iend,
+ unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x8_u(unsigned long ibuf, unsigned long iend,
+ unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x8_s(unsigned long ibuf, unsigned long iend,
+ unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x8_s(unsigned long ibuf, unsigned long iend,
+ unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x16_s(unsigned long ibuf, unsigned long iend,
+ unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x16_s(unsigned long ibuf, unsigned long iend,
+ unsigned long obuf, int mask);
/*
* DMA Interrupt handler
diff --git a/drivers/sound/vidc_audio.c b/drivers/sound/vidc_audio.c
index a59a077f3..7aa275084 100644
--- a/drivers/sound/vidc_audio.c
+++ b/drivers/sound/vidc_audio.c
@@ -8,6 +8,8 @@
#include <asm/hardware.h>
#include <asm/io.h>
+#include <asm/system.h>
+
#include "sound_config.h"
#include "vidc.h"
@@ -22,7 +24,7 @@ static int vidc_adev;
static int vidc_audio_volume;
static int vidc_audio_rate;
-static char vidc_audio_bits;
+static char vidc_audio_format;
static char vidc_audio_channels;
extern void vidc_update_filler(int bits, int channels);
@@ -38,23 +40,25 @@ int vidc_audio_set_volume(int newvol)
return vidc_audio_volume;
}
-static int vidc_audio_set_bits(int bits)
+static int vidc_audio_set_bits(int fmt)
{
- switch (bits)
+printk("setting format: %d\n", fmt);
+ switch (fmt)
{
case AFMT_QUERY:
break;
case AFMT_U8:
+ case AFMT_S8:
case AFMT_S16_LE:
- vidc_audio_bits = bits;
- vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+ vidc_audio_format = fmt;
+ vidc_update_filler(vidc_audio_format, vidc_audio_channels);
break;
default:
- vidc_audio_bits = 16;
- vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+ vidc_audio_format = AFMT_S16_LE;
+ vidc_update_filler(vidc_audio_format, vidc_audio_channels);
break;
}
- return vidc_audio_bits;
+ return vidc_audio_format;
}
static int vidc_audio_set_rate(int rate)
@@ -68,8 +72,8 @@ static int vidc_audio_set_rate(int rate)
vidc_audio_rate = 3;
if (vidc_audio_rate > 255)
vidc_audio_rate = 255;
- outl((vidc_audio_rate - 2) | 0xb0000000, VIDC_BASE);
- outl(0xb1000003, VIDC_BASE);
+ outl((vidc_audio_rate - 2) | 0xb0000000, IO_VIDC_BASE);
+ outl(0xb1000003, IO_VIDC_BASE);
newsize = (10000 / vidc_audio_rate) & ~3;
if (newsize < 208)
newsize = 208;
@@ -92,11 +96,11 @@ static int vidc_audio_set_channels(int channels)
case 1:
case 2:
vidc_audio_channels = channels;
- vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+ vidc_update_filler(vidc_audio_format, vidc_audio_channels);
break;
default:
vidc_audio_channels = 2;
- vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+ vidc_update_filler(vidc_audio_format, vidc_audio_channels);
break;
}
return vidc_audio_channels;
@@ -110,7 +114,6 @@ static int vidc_audio_set_channels(int channels)
*
* Called when opening the DMAbuf (dmabuf.c:259)
*/
-
static int vidc_audio_open(int dev, int mode)
{
if (vidc_busy)
@@ -133,7 +136,6 @@ static int vidc_audio_open(int dev, int mode)
* Called when closing the DMAbuf (dmabuf.c:477)
* after halt_xfer
*/
-
static void vidc_audio_close(int dev)
{
vidc_busy = 0;
@@ -205,23 +207,23 @@ static int vidc_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
* 2. (dmabuf.c:1504)
* 3. A new buffer needs to be sent to the device (dmabuf.c:1579)
*/
-
-static void vidc_audio_dma_interrupt(void)
-{
- DMAbuf_outputintr(vidc_adev, 1);
-}
-
static void vidc_audio_output_block(int dev, unsigned long buf, int total_count,
int intrflag)
{
- dma_start = buf;
+ struct audio_operations *adev = audio_devs[dev];
+ struct dma_buffparms *dmap = adev->dmap_out;
+
+ dma_start = buf - (unsigned long)dmap->raw_buf_phys + (unsigned long)dmap->raw_buf;
dma_count = total_count;
- if (!intrflag)
+ if (!(adev->flags & DMA_ACTIVE))
{
- dma_interrupt = vidc_audio_dma_interrupt;
+ unsigned long flags;
+printk("kicking output: %lX+%lX [%lX]\n", dma_start, dma_count, *(unsigned long *)dma_start);
+ save_flags_cli(flags);
vidc_sound_dma_irq(0, NULL, NULL);
- outb(DMA_CR_D | DMA_CR_E, IOMD_SD0CR);
+ outb(DMA_CR_E | 0x10, IOMD_SD0CR);
+ restore_flags(flags);
}
}
@@ -235,6 +237,11 @@ static int vidc_audio_prepare_for_input(int dev, int bsize, int bcount)
return -EINVAL;
}
+static void vidc_audio_dma_interrupt(void)
+{
+ DMAbuf_outputintr(vidc_adev, 1);
+}
+
/*
* Prepare for outputting samples to `dev'
*
@@ -246,34 +253,27 @@ static int vidc_audio_prepare_for_input(int dev, int bsize, int bcount)
* 2. We get a write buffer without dma_mode setup (dmabuf.c:1152)
* 3. We restart a transfer (dmabuf.c:1324)
*/
-
static int vidc_audio_prepare_for_output(int dev, int bsize, int bcount)
{
+ audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
+ dma_interrupt = vidc_audio_dma_interrupt;
return 0;
}
-static void vidc_audio_reset(int dev)
-{
-}
-
/*
- * Halt a DMA transfer to `dev'
- *
- * Called when:
- * 1. We close the DMAbuf (dmabuf.c:476)
- * 2. We run out of output buffers to output to the device. (dmabuf.c:1456)
- * 3. We run out of output buffers and we're closing down. (dmabuf.c:1546)
- * 4. We run out of input buffers in AUTOMODE. (dmabuf.c:1651)
+ * Stop our current operation.
*/
-
-static void vidc_audio_halt_xfer(int dev)
+static void vidc_audio_reset(int dev)
{
- dma_count = 0;
+ /* stop interrupts. Our real interrupt routine
+ * will close DMA down for us
+ */
+ dma_interrupt = NULL;
}
static int vidc_audio_local_qlen(int dev)
{
- return dma_count != 0;
+ return /*dma_count !=*/ 0;
}
static struct audio_driver vidc_audio_driver =
@@ -286,35 +286,28 @@ static struct audio_driver vidc_audio_driver =
vidc_audio_prepare_for_input, /* prepare_for_input */
vidc_audio_prepare_for_output, /* prepare_for_output */
vidc_audio_reset, /* reset */
- vidc_audio_halt_xfer, /* halt_xfer */
vidc_audio_local_qlen, /*+local_qlen */
NULL, /*+copy_from_user */
NULL, /*+halt_input */
- NULL, /*+halt_output */
+ NULL, /* halt_output */
NULL, /*+trigger */
NULL, /*+set_speed */
NULL, /*+set_bits */
NULL, /*+set_channels */
};
-static struct audio_operations vidc_audio_operations =
-{
- "VIDCsound",
- 0,
- AFMT_U8 | AFMT_S16_LE,
- NULL,
- &vidc_audio_driver
-};
-
void vidc_audio_init(struct address_info *hw_config)
{
vidc_audio_volume = 100 | (100 << 8);
- if ((vidc_adev = sound_alloc_audiodev())!=-1)
+
+ if ((vidc_adev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
+ "VIDCsound", &vidc_audio_driver,
+ sizeof(struct audio_driver),
+ DMA_AUTOMODE, AFMT_U8 | AFMT_S8 | AFMT_S16_LE,
+ NULL, hw_config->dma, hw_config->dma2)) >= 0)
{
- audio_devs[vidc_adev] = &vidc_audio_operations;
audio_devs[vidc_adev]->min_fragment = 10; /* 1024 bytes => 64 buffers */
audio_devs[vidc_adev]->mixer_dev = num_mixers;
- audio_devs[vidc_adev]->flags |= 0;
}
else printk(KERN_ERR "VIDCsound: Too many PCM devices available\n");
}
diff --git a/drivers/sound/vidc_fill.S b/drivers/sound/vidc_fill.S
index 841fe5b96..b8b1e6620 100644
--- a/drivers/sound/vidc_fill.S
+++ b/drivers/sound/vidc_fill.S
@@ -12,11 +12,12 @@
.text
-ENTRY(vidc_fill_1x8)
+ENTRY(vidc_fill_1x8_u)
mov ip, #0xff00
1: cmp r0, r1
bge SYMBOL_NAME(vidc_clear)
ldrb r4, [r0], #1
+ eor r4, r4, #0x80
and r4, ip, r4, lsl #8
orr r4, r4, r4, lsl #16
str r4, [r2], #4
@@ -24,7 +25,7 @@ ENTRY(vidc_fill_1x8)
blt 1b
mov pc, lr
-ENTRY(vidc_fill_2x8)
+ENTRY(vidc_fill_2x8_u)
mov ip, #0xff00
1: cmp r0, r1
bge SYMBOL_NAME(vidc_clear)
@@ -38,7 +39,33 @@ ENTRY(vidc_fill_2x8)
blt 1b
mov pc, lr
-ENTRY(vidc_fill_1x16)
+ENTRY(vidc_fill_1x8_s)
+ mov ip, #0xff00
+1: cmp r0, r1
+ bge SYMBOL_NAME(vidc_clear)
+ ldrb r4, [r0], #1
+ and r4, ip, r4, lsl #8
+ orr r4, r4, r4, lsl #16
+ str r4, [r2], #4
+ cmp r2, r3
+ blt 1b
+ mov pc, lr
+
+ENTRY(vidc_fill_2x8_s)
+ mov ip, #0xff00
+1: cmp r0, r1
+ bge SYMBOL_NAME(vidc_clear)
+ ldr r4, [r0], #2
+ and r5, r4, ip
+ and r4, ip, r4, lsl #8
+ orr r4, r4, r5, lsl #16
+ orr r4, r4, r4, lsr #8
+ str r4, [r2], #4
+ cmp r2, r3
+ blt 1b
+ mov pc, lr
+
+ENTRY(vidc_fill_1x16_s)
mov ip, #0xff00
orr ip, ip, ip, lsr #8
1: cmp r0, r1
@@ -56,7 +83,7 @@ ENTRY(vidc_fill_1x16)
blt 1b
mov pc, lr
-ENTRY(vidc_fill_2x16)
+ENTRY(vidc_fill_2x16_s)
mov ip, #0xff00
orr ip, ip, ip, lsr #8
1: cmp r0, r1
@@ -103,26 +130,26 @@ ENTRY(vidc_clear)
*/
ENTRY(vidc_sound_dma_irq)
- stmfd sp!, {r4 - r9, lr}
- ldr r9, =SYMBOL_NAME(dma_start)
- ldmia r9, {r0, r1, r2, r3, r4, r5}
+ stmfd sp!, {r4 - r8, lr}
+ ldr r8, =SYMBOL_NAME(dma_start)
+ ldmia r8, {r0, r1, r2, r3, r4, r5}
teq r1, #0
adreq r4, SYMBOL_NAME(vidc_fill_noaudio)
- moveq r8, #1 << 31
- movne r8, #0
+ moveq r7, #1 << 31
+ movne r7, #0
mov ip, #IOMD_BASE & 0xff000000
orr ip, ip, #IOMD_BASE & 0x00ff0000
- ldrb r7, [ip, #IOMD_SD0ST]
- tst r7, #DMA_ST_OFL @ Check for overrun
- eorne r7, r7, #DMA_ST_AB
- tst r7, #DMA_ST_AB
+ ldrb r6, [ip, #IOMD_SD0ST]
+ tst r6, #DMA_ST_OFL @ Check for overrun
+ eorne r6, r6, #DMA_ST_AB
+ tst r6, #DMA_ST_AB
moveq r2, r3 @ DMAing A, update B
add r3, r2, r5 @ End of DMA buffer
add r1, r1, r0 @ End of virtual DMA buffer
mov lr, pc
- mov pc, r4 @ Call fill routine
+ mov pc, r4 @ Call fill routine (uses r4, ip)
sub r1, r1, r0 @ Remaining length
- stmia r9, {r0, r1}
+ stmia r8, {r0, r1}
mov r0, #0
tst r2, #4 @ Round buffer up to 4 words
strne r0, [r2], #4
@@ -133,29 +160,31 @@ ENTRY(vidc_sound_dma_irq)
mov r2, r2, lsl #20
movs r2, r2, lsr #20
orreq r2, r2, #1 << 30 @ Set L bit
- orr r2, r2, r8
- ldmdb r9, {r3, r4, r5}
- tst r7, #DMA_ST_AB
+ orr r2, r2, r7
+ ldmdb r8, {r3, r4, r5}
+ tst r6, #DMA_ST_AB
mov ip, #IOMD_BASE & 0xff000000
orr ip, ip, #IOMD_BASE & 0x00ff0000
streq r4, [ip, #IOMD_SD0CURB]
strne r5, [ip, #IOMD_SD0CURA]
streq r2, [ip, #IOMD_SD0ENDB]
strne r2, [ip, #IOMD_SD0ENDA]
- ldr r6, [ip, #IOMD_SD0ST]
- tst r6, #DMA_ST_OFL
+ ldr lr, [ip, #IOMD_SD0ST]
+ tst lr, #DMA_ST_OFL
bne 1f
- tst r7, #DMA_ST_AB
+ tst r6, #DMA_ST_AB
strne r4, [ip, #IOMD_SD0CURB]
streq r5, [ip, #IOMD_SD0CURA]
strne r2, [ip, #IOMD_SD0ENDB]
streq r2, [ip, #IOMD_SD0ENDA]
-1: teq r8, #0
+1: teq r7, #0
mov r0, #0x10
strneb r0, [ip, #IOMD_SD0CR]
- teqeq r1, #0
- ldmfd sp!, {r4 - r9, lr}
- moveq pc, r3 @ Call interrupt routine
+ ldmfd sp!, {r4 - r8, lr}
+ teq r1, #0 @ If we have no more
+ movne pc, lr
+ teq r3, #0
+ movne pc, r3 @ Call interrupt routine
mov pc, lr
.data
diff --git a/drivers/sound/vidc_mixer.c b/drivers/sound/vidc_mixer.c
index 1bdb1e88e..01be4925c 100644
--- a/drivers/sound/vidc_mixer.c
+++ b/drivers/sound/vidc_mixer.c
@@ -47,13 +47,15 @@ static int vidc_default_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
break;
case SOUND_MIXER_READ_SYNTH:
- ret = vidc_synth_get_volume();
+// ret = vidc_synth_get_volume();
+ ret = 0;
break;
case SOUND_MIXER_WRITE_SYNTH:
if (get_user(ret, (int *) arg))
return -EINVAL;
- ret = vidc_synth_set_volume(ret);
+// ret = vidc_synth_set_volume(ret);
+ ret = 0;
break;
case SOUND_MIXER_READ_PCM:
diff --git a/drivers/sound/vidc_synth.c b/drivers/sound/vidc_synth.c
index 7e6797e8e..ba94f0bc6 100644
--- a/drivers/sound/vidc_synth.c
+++ b/drivers/sound/vidc_synth.c
@@ -8,7 +8,7 @@
#include "sound_config.h"
#include "vidc.h"
-
+#if 0
static struct synth_info vidc_info =
{
"VIDCsound", /* name */
@@ -42,31 +42,32 @@ static void vidc_synth_close(int dev)
static struct synth_operations vidc_synth_operations =
{
- &vidc_info, /* info */
- 0, /* midi_dev */
- SYNTH_TYPE_SAMPLE, /* synth_type */
- /*SAMPLE_TYPE_XXX */ 0,
- /* SAMPLE_TYPE GUS *//* synth_subtype */
- vidc_synth_open, /* open */
- vidc_synth_close, /* close */
- NULL, /* ioctl */
- NULL, /* kill_note */
- NULL, /* start_note */
- NULL, /* set_instr */
- NULL, /* reset */
- NULL, /* hw_control */
- NULL, /* load_patch */
- NULL, /* aftertouch */
- NULL, /* controller */
- NULL, /* panning */
- NULL, /* volume_method */
- NULL, /* patchmgr */
- NULL, /* bender */
- NULL, /* alloc */
- NULL, /* setup_voice */
- NULL, /* send_sysex */
- /* alloc */
- /* chn_info[16] */
+ "VIDC Synth", /* name */
+ &vidc_info, /* info */
+ 0, /* midi_dev */
+ SYNTH_TYPE_SAMPLE, /* synth_type */
+ /*SAMPLE_TYPE_XXX */ 0, /* synth_subtype */
+ vidc_synth_open, /* open */
+ vidc_synth_close, /* close */
+ NULL, /* ioctl */
+ NULL, /* kill_note */
+ NULL, /* start_note */
+ NULL, /* set_instr */
+ NULL, /* reset */
+ NULL, /* hw_control */
+ NULL, /* load_patch */
+ NULL, /* aftertouch */
+ NULL, /* controller */
+ NULL, /* panning */
+ NULL, /* volume_method */
+ NULL, /* bender */
+ NULL, /* alloc_voice */
+ NULL, /* setup_voice */
+ NULL, /* send_sysex */
+ /* alloc */
+ /* chn_info[16] */
+ /* syex_buf */
+ /* syex_ptr */
};
int vidc_synth_get_volume(void)
@@ -87,3 +88,4 @@ void vidc_synth_init(struct address_info *hw_config)
else
printk(KERN_ERR "VIDCsound: Too many synthesizers\n");
}
+#endif
diff --git a/drivers/sound/waveartist.c b/drivers/sound/waveartist.c
new file mode 100644
index 000000000..5a707a4b7
--- /dev/null
+++ b/drivers/sound/waveartist.c
@@ -0,0 +1,1956 @@
+/*
+ * drivers/sound/waveartist.c
+ *
+ * The low level driver for the RWA010 Rockwell Wave Artist
+ * codec chip used in the Corel Computer NetWinder.
+ *
+ * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk)
+ */
+
+/*
+ * Copyright (C) by Corel Computer 1998
+ *
+ * RWA010 specs received under NDA from Rockwell
+ *
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+
+/* Debugging */
+#define DEBUG_CMD 1
+#define DEBUG_OUT 2
+#define DEBUG_IN 4
+#define DEBUG_INTR 8
+#define DEBUG_MIXER 16
+#define DEBUG_TRIGGER 32
+
+#define debug_flg (0)
+
+#define DEB(x)
+#define DDB(x)
+#define DEB1(x)
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/hardware.h>
+
+#include "soundmodule.h"
+#include "sound_config.h"
+#include "waveartist.h"
+
+#define VNC_TIMER_PERIOD (HZ/4) //check slider 4 times/sec
+
+#define MIXER_PRIVATE3_RESET 0x53570000
+#define MIXER_PRIVATE3_READ 0x53570001
+#define MIXER_PRIVATE3_WRITE 0x53570002
+
+#define VNC_INTERNAL_SPKR 0x01 //the sw mute on/off control bit
+#define VNC_INTERNAL_MIC 0x10 //the hw internal/handset mic bit
+
+/* Use RECSRC = speaker to mark the internal microphone
+ *
+ * Some cheating involved here: there is no way to relay
+ * to the system, which microphone in in use
+ * (left = handset, or right = internal)
+ *
+ * So while I do not flag SPEAKER in the Recording Devices
+ * Mask, when on internal
+ *
+ * mike - I set the speaker bit hi. Some mixers can be
+ * confused a bit...
+ */
+
+#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_LINE |\
+ SOUND_MASK_MIC |\
+ SOUND_MASK_LINE1) //Line1 = analog phone
+
+#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH |\
+ SOUND_MASK_PCM |\
+ SOUND_MASK_LINE |\
+ SOUND_MASK_MIC | \
+ SOUND_MASK_LINE1 |\
+ SOUND_MASK_RECLEV |\
+ SOUND_MASK_VOLUME)
+
+static unsigned short levels[SOUND_MIXER_NRDEVICES] = {
+ 0x5555, /* Master Volume */
+ 0x0000, /* Bass */
+ 0x0000, /* Treble */
+ 0x5555, /* Synth (FM) */
+ 0x4b4b, /* PCM */
+ 0x0000, /* PC Speaker */
+ 0x0000, /* Ext Line */
+ 0x0000, /* Mic */
+ 0x0000, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x0000, /* SB PCM (ALT PCM) */
+ 0x0000, /* Recording level */
+ 0x0000, /* Input gain */
+ 0x0000, /* Output gain */
+ 0x0000, /* Line1 (Aux1) */
+ 0x0000, /* Line2 (Aux2) */
+ 0x0000, /* Line3 (Aux3) */
+ 0x0000, /* Digital1 */
+ 0x0000, /* Digital2 */
+ 0x0000, /* Digital3 */
+ 0x0000, /* Phone In */
+ 0x0000, /* Phone Out */
+ 0x0000, /* Video */
+ 0x0000, /* Radio */
+ 0x0000 /* Monitor */
+};
+
+typedef struct {
+ struct address_info hw; /* hardware */
+ char *chip_name;
+
+ int xfer_count;
+ int audio_mode;
+ int open_mode;
+ int audio_flags;
+ int record_dev;
+ int playback_dev;
+ int dev_no;
+
+ /* Mixer parameters */
+ unsigned short *levels;
+ int handset_state;
+ signed int slider_vol; /* hardware slider volume */
+ int recmask; /* currently enabled recording device! */
+ int supported_devices; /* SUPPORTED_MIXER_DEVICES */
+ int rec_devices; /* POSSIBLE_RECORDING_DEVICES */
+ int handset_mute_sw :1;/* 1 - handset controlled in sw */
+ int use_slider :1;/* use slider setting for o/p vol */
+ int mute_state :1;
+} wavnc_info;
+
+typedef struct wavnc_port_info {
+ int open_mode;
+ int speed;
+ int channels;
+ int audio_format;
+} wavnc_port_info;
+
+static int nr_waveartist_devs;
+static wavnc_info adev_info[MAX_AUDIO_DEV];
+static struct timer_list vnc_timer;
+
+
+static inline void
+waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char set)
+{
+ unsigned int ctlr_port = hw->io_base + CTLR;
+
+ clear = ~clear & inb(ctlr_port);
+
+ outb(clear | set, ctlr_port);
+}
+
+/* Toggle IRQ acknowledge line
+ */
+static inline void
+waveartist_iack(wavnc_info *devc)
+{
+ unsigned int ctlr_port = devc->hw.io_base + CTLR;
+ int old_ctlr;
+
+ old_ctlr = inb(ctlr_port) & ~IRQ_ACK;
+
+ outb(old_ctlr | IRQ_ACK, ctlr_port);
+ outb(old_ctlr, ctlr_port);
+}
+
+static inline int
+waveartist_sleep(int timeout_ms)
+{
+ unsigned int timeout = timeout_ms * 10 * HZ / 100;
+
+ do {
+ current->state = TASK_INTERRUPTIBLE;
+ timeout = schedule_timeout(timeout);
+ } while (timeout);
+
+ return 0;
+}
+
+static int
+waveartist_reset(wavnc_info *devc)
+{
+ struct address_info *hw = &devc->hw;
+ unsigned int timeout, res = -1;
+
+ waveartist_set_ctlr(hw, -1, RESET);
+ waveartist_sleep(2);
+ waveartist_set_ctlr(hw, RESET, 0);
+
+ timeout = 500;
+ do {
+ mdelay(2);
+
+ if (inb(hw->io_base + STATR) & CMD_RF) {
+ res = inw(hw->io_base + CMDR);
+ if (res == 0x55aa)
+ break;
+ }
+ } while (timeout--);
+
+ if (timeout == 0) {
+ printk("WaveArtist: reset timeout ");
+ if (res != (unsigned int)-1)
+ printk("(res=%04X)", res);
+ printk("\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int
+waveartist_cmd(wavnc_info *devc,
+ int nr_cmd, unsigned int *cmd,
+ int nr_resp, unsigned int *resp)
+{
+ unsigned int io_base = devc->hw.io_base;
+ unsigned int timed_out = 0;
+ unsigned int i;
+
+ if (debug_flg & DEBUG_CMD) {
+ printk("waveartist_cmd: cmd=");
+
+ for (i = 0; i < nr_cmd; i++)
+ printk("%04X ", cmd[i]);
+
+ printk("\n");
+ }
+
+ if (inb(io_base + STATR) & CMD_RF) {
+ int old_data;
+
+ /* flush the port
+ */
+
+ old_data = inw(io_base + CMDR);
+
+ if (debug_flg & DEBUG_CMD)
+ printk("flushed %04X...", old_data);
+
+ udelay(10);
+ }
+
+ for (i = 0; !timed_out && i < nr_cmd; i++) {
+ int count;
+
+ for (count = 5000; count; count--)
+ if (inb(io_base + STATR) & CMD_WE)
+ break;
+
+ if (!count)
+ timed_out = 1;
+ else
+ outw(cmd[i], io_base + CMDR);
+ }
+
+ for (i = 0; !timed_out && i < nr_resp; i++) {
+ int count;
+
+ for (count = 5000; count; count--)
+ if (inb(io_base + STATR) & CMD_RF)
+ break;
+
+ if (!count)
+ timed_out = 1;
+ else
+ resp[i] = inw(io_base + CMDR);
+ }
+
+ if (debug_flg & DEBUG_CMD) {
+ if (!timed_out) {
+ printk("waveartist_cmd: resp=");
+
+ for (i = 0; i < nr_resp; i++)
+ printk("%04X ", resp[i]);
+
+ printk("\n");
+ } else
+ printk("waveartist_cmd: timed out\n");
+ }
+
+ return timed_out ? 1 : 0;
+}
+
+static inline int
+waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg)
+{
+ unsigned int vals[2];
+
+ vals[0] = cmd;
+ vals[1] = arg;
+
+ waveartist_cmd(devc, 2, vals, 1, vals);
+
+ return 0;
+}
+
+static inline int
+waveartist_cmd3(wavnc_info *devc, unsigned int cmd,
+ unsigned int arg1, unsigned int arg2)
+{
+ unsigned int vals[3];
+
+ vals[0] = cmd;
+ vals[1] = arg1;
+ vals[2] = arg2;
+
+ return waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static int
+waveartist_sendcmd(struct address_info *hw, unsigned int cmd)
+{
+ int count;
+
+ if (debug_flg & DEBUG_CMD)
+ printk("waveartist_sendcmd: cmd=0x%04X...", cmd);
+
+ udelay(10);
+
+ if (inb(hw->io_base + STATR) & CMD_RF) {
+ /*
+ * flush the port
+ */
+ count = inw(hw->io_base + CMDR);
+
+ udelay(10);
+
+ if (debug_flg & DEBUG_CMD)
+ printk(" flushed %04X...", count);
+ }
+
+ /*
+ * preset timeout at 5000 loops
+ */
+ count = 5000;
+
+ while (count --)
+ if (inb(hw->io_base + STATR) & CMD_WE) {
+ /* wait till CMD_WE is high
+ * then output the command
+ */
+ outw(cmd, hw->io_base + CMDR);
+ break;
+ }
+
+ /* ready BEFORE timeout?
+ */
+ if (debug_flg & DEBUG_CMD)
+ printk(" %s\n", count ? "Done OK." : "Error!");
+
+ udelay(10);
+
+ return count ? 0 : 1;
+}
+
+static int
+waveartist_getrev(struct address_info *hw, char *rev)
+{
+ int temp;
+
+ waveartist_sendcmd(hw, 0);
+ udelay(20);
+ temp = inw(hw->io_base + CMDR);
+ udelay(20);
+ inw(hw->io_base + CMDR); // discard second word == 0
+
+ rev[0] = temp >> 8;
+ rev[1] = temp & 255;
+ rev[2] = '\0';
+
+ return temp;
+}
+
+inline void
+waveartist_mute(wavnc_info *devc, int mute)
+{
+}
+
+static void waveartist_halt_output(int dev);
+static void waveartist_halt_input(int dev);
+static void waveartist_halt(int dev);
+static void waveartist_trigger(int dev, int state);
+
+static int
+waveartist_open(int dev, int mode)
+{
+ wavnc_info *devc;
+ wavnc_port_info *portc;
+ unsigned long flags;
+
+ if (dev < 0 || dev >= num_audiodevs)
+ return -ENXIO;
+
+ devc = (wavnc_info *) audio_devs[dev]->devc;
+ portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ save_flags(flags);
+ cli();
+ if (portc->open_mode || (devc->open_mode & mode)) {
+ restore_flags(flags);
+ return -EBUSY;
+ }
+
+ devc->audio_mode = 0;
+ devc->open_mode |= mode;
+ portc->open_mode = mode;
+ waveartist_trigger(dev, 0);
+
+ if (mode & OPEN_READ)
+ devc->record_dev = dev;
+ if (mode & OPEN_WRITE)
+ devc->playback_dev = dev;
+ restore_flags(flags);
+
+ /*
+ * Mute output until the playback really starts. This
+ * decreases clicking (hope so).
+ */
+ waveartist_mute(devc, 1);
+
+ return 0;
+}
+
+static void
+waveartist_close(int dev)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ waveartist_halt(dev);
+
+ devc->audio_mode = 0;
+ devc->open_mode &= ~portc->open_mode;
+ portc->open_mode = 0;
+
+ waveartist_mute(devc, 1);
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+ unsigned int count = __count;
+
+ if (debug_flg & DEBUG_OUT)
+ printk("waveartist: output block, buf=0x%lx, count=0x%x...\n",
+ buf, count);
+ /*
+ * 16 bit data
+ */
+ if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))
+ count >>= 1;
+
+ if (portc->channels > 1)
+ count >>= 1;
+
+ count -= 1;
+
+ if (devc->audio_mode & PCM_ENABLE_OUTPUT &&
+ audio_devs[dev]->flags & DMA_AUTOMODE &&
+ intrflag &&
+ count == devc->xfer_count) {
+ devc->audio_mode |= PCM_ENABLE_OUTPUT;
+ return; /*
+ * Auto DMA mode on. No need to react
+ */
+ }
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * set sample count
+ */
+ waveartist_cmd2(devc, 0x0024, count);
+
+ devc->xfer_count = count;
+ devc->audio_mode |= PCM_ENABLE_OUTPUT;
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+ unsigned int count = __count;
+
+ if (debug_flg & DEBUG_IN)
+ printk("waveartist: start input, buf=0x%lx, count=0x%x...\n",
+ buf, count);
+
+ if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */
+ count >>= 1;
+
+ if (portc->channels > 1)
+ count >>= 1;
+
+ count -= 1;
+
+ if (devc->audio_mode & PCM_ENABLE_INPUT &&
+ audio_devs[dev]->flags & DMA_AUTOMODE &&
+ intrflag &&
+ count == devc->xfer_count) {
+ devc->audio_mode |= PCM_ENABLE_INPUT;
+ return; /*
+ * Auto DMA mode on. No need to react
+ */
+ }
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * set sample count
+ */
+ waveartist_cmd2(devc, 0x0014, count);
+ waveartist_mute(devc, 0);
+
+ devc->xfer_count = count;
+ devc->audio_mode |= PCM_ENABLE_INPUT;
+
+ restore_flags(flags);
+}
+
+static int
+waveartist_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+ return -EINVAL;
+}
+
+static unsigned int
+waveartist_get_speed(wavnc_port_info *portc)
+{
+ unsigned int speed;
+
+ /*
+ * program the speed, channels, bits
+ */
+ if (portc->speed == 8000)
+ speed = 0x2E71;
+ else if (portc->speed == 11025)
+ speed = 0x4000;
+ else if (portc->speed == 22050)
+ speed = 0x8000;
+ else if (portc->speed == 44100)
+ speed = 0x0;
+ else {
+ /*
+ * non-standard - just calculate
+ */
+ speed = portc->speed << 16;
+
+ speed = (speed / 44100) & 65535;
+ }
+
+ return speed;
+}
+
+static unsigned int
+waveartist_get_bits(wavnc_port_info *portc)
+{
+ unsigned int bits;
+
+ if (portc->audio_format == AFMT_S16_LE)
+ bits = 1;
+ else if (portc->audio_format == AFMT_S8)
+ bits = 0;
+ else
+ bits = 2; //default AFMT_U8
+
+ return bits;
+}
+
+static int
+waveartist_prepare_for_input(int dev, int bsize, int bcount)
+{
+ unsigned long flags;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned int speed, bits;
+
+ if (devc->audio_mode)
+ return 0;
+
+ speed = waveartist_get_speed(portc);
+ bits = waveartist_get_bits(portc);
+
+ save_flags(flags);
+ cli();
+
+ if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
+ printk("waveartist: error setting the record format to %d\n",
+ portc->audio_format);
+
+ if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels))
+ printk("waveartist: error setting record to %d channels\n",
+ portc->channels);
+
+ /*
+ * write cmd SetSampleSpeedTimeConstant
+ */
+ if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed))
+ printk("waveartist: error setting the record speed "
+ "to %dHz.\n", portc->speed);
+
+ if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1))
+ printk("waveartist: error setting the record data path "
+ "to 0x%X\n", 1);
+
+ if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
+ printk("waveartist: error setting the record format to %d\n",
+ portc->audio_format);
+
+ devc->xfer_count = 0;
+ restore_flags(flags);
+ waveartist_halt_input(dev);
+
+ if (debug_flg & DEBUG_INTR) {
+ printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
+ printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
+ printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
+ }
+
+ return 0;
+}
+
+static int
+waveartist_prepare_for_output(int dev, int bsize, int bcount)
+{
+ unsigned long flags;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned int speed, bits;
+
+ /*
+ * program the speed, channels, bits
+ */
+ speed = waveartist_get_speed(portc);
+ bits = waveartist_get_bits(portc);
+
+ save_flags(flags);
+ cli();
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) &&
+ waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed))
+ printk("waveartist: error setting the playback speed "
+ "to %dHz.\n", portc->speed);
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels))
+ printk("waveartist: error setting the playback to"
+ " %d channels\n", portc->channels);
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0))
+ printk("waveartist: error setting the playback data path "
+ "to 0x%X\n", 0);
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits))
+ printk("waveartist: error setting the playback format to %d\n",
+ portc->audio_format);
+
+ devc->xfer_count = 0;
+ restore_flags(flags);
+ waveartist_halt_output(dev);
+
+ if (debug_flg & DEBUG_INTR) {
+ printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
+ printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
+ printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
+ }
+
+ return 0;
+}
+
+static void
+waveartist_halt(int dev)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ wavnc_info *devc;
+
+
+ if (portc->open_mode & OPEN_WRITE)
+ waveartist_halt_output(dev);
+
+ if (portc->open_mode & OPEN_READ)
+ waveartist_halt_input(dev);
+
+ devc = (wavnc_info *) audio_devs[dev]->devc;
+ devc->audio_mode = 0;
+}
+
+static void
+waveartist_halt_input(int dev)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ waveartist_mute(devc, 1);
+
+//RMK disable_dma(audio_devs[dev]->dmap_in->dma);
+
+ /*
+ * Stop capture
+ */
+ waveartist_sendcmd(&devc->hw, 0x17);
+
+//RMK enable_dma(audio_devs[dev]->dmap_in->dma);
+ devc->audio_mode &= ~PCM_ENABLE_INPUT;
+
+ /*
+ * Clear interrupt by toggling
+ * the IRQ_ACK bit in CTRL
+ */
+ if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
+ waveartist_iack(devc);
+
+// devc->audio_mode &= ~PCM_ENABLE_INPUT;
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_halt_output(int dev)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ waveartist_mute(devc, 1);
+
+//RMK disable_dma(audio_devs[dev]->dmap_out->dma);
+
+ waveartist_sendcmd(&devc->hw, 0x27);
+
+//RMK enable_dma(audio_devs[dev]->dmap_out->dma);
+
+ devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+
+ /*
+ * Clear interrupt by toggling
+ * the IRQ_ACK bit in CTRL
+ */
+ if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
+ waveartist_iack(devc);
+
+// devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_trigger(int dev, int state)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned long flags;
+
+ if (debug_flg & DEBUG_TRIGGER) {
+ printk("wavnc: audio trigger ");
+ if (state & PCM_ENABLE_INPUT)
+ printk("in ");
+ if (state & PCM_ENABLE_OUTPUT)
+ printk("out");
+ printk("\n");
+ }
+
+ save_flags(flags);
+ cli();
+
+ state &= devc->audio_mode;
+
+ if (portc->open_mode & OPEN_READ &&
+ state & PCM_ENABLE_INPUT)
+ /*
+ * enable ADC Data Transfer to PC
+ */
+ waveartist_sendcmd(&devc->hw, 0x15);
+
+ if (portc->open_mode & OPEN_WRITE &&
+ state & PCM_ENABLE_OUTPUT)
+ /*
+ * enable DAC data transfer from PC
+ */
+ waveartist_sendcmd(&devc->hw, 0x25);
+
+ waveartist_mute(devc, 0);
+
+ restore_flags(flags);
+}
+
+static int
+waveartist_set_speed(int dev, int arg)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ if (arg <= 0)
+ return portc->speed;
+
+ if (arg < 5000)
+ arg = 5000;
+ if (arg > 44100)
+ arg = 44100;
+
+ portc->speed = arg;
+ return portc->speed;
+
+}
+
+static short
+waveartist_set_channels(int dev, short arg)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ if (arg != 1 && arg != 2)
+ return portc->channels;
+
+ portc->channels = arg;
+ return arg;
+}
+
+static unsigned int
+waveartist_set_bits(int dev, unsigned int arg)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ if (arg == 0)
+ return portc->audio_format;
+
+ if ((arg != AFMT_U8) && (arg != AFMT_S16_LE) && (arg != AFMT_S8))
+ arg = AFMT_U8;
+
+ portc->audio_format = arg;
+
+ return arg;
+}
+
+static struct audio_driver waveartist_audio_driver = {
+ waveartist_open,
+ waveartist_close,
+ waveartist_output_block,
+ waveartist_start_input,
+ waveartist_ioctl,
+ waveartist_prepare_for_input,
+ waveartist_prepare_for_output,
+ waveartist_halt,
+ NULL,
+ NULL,
+ waveartist_halt_input,
+ waveartist_halt_output,
+ waveartist_trigger,
+ waveartist_set_speed,
+ waveartist_set_bits,
+ waveartist_set_channels
+};
+
+
+static void
+waveartist_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ wavnc_info *devc = (wavnc_info *)dev_id;
+ int irqstatus, status;
+
+ irqstatus = inb(devc->hw.io_base + IRQSTAT);
+ status = inb(devc->hw.io_base + STATR);
+
+ if (debug_flg & DEBUG_INTR)
+ printk("waveartist_intr: stat=%02x, irqstat=%02x\n",
+ status, irqstatus);
+
+ if (status & IRQ_REQ) /* Clear interrupt */
+ waveartist_iack(devc);
+ else
+ printk("waveartist: unexpected interrupt\n");
+
+#ifdef CONFIG_AUDIO
+ if (irqstatus & 0x01) {
+ int temp = 1;
+
+ /* PCM buffer done
+ */
+ if ((status & DMA0) && (devc->audio_mode & PCM_ENABLE_OUTPUT)) {
+ DMAbuf_outputintr(devc->playback_dev, 1);
+ temp = 0;
+ }
+ if ((status & DMA1) && (devc->audio_mode & PCM_ENABLE_INPUT)) {
+ DMAbuf_inputintr(devc->record_dev);
+ temp = 0;
+ }
+ if (temp) //default:
+ printk("WaveArtist: Unknown interrupt\n");
+ }
+#endif
+ if (irqstatus & 0x2)
+ // We do not use SB mode natively...
+ printk("WaveArtist: Unexpected SB interrupt...\n");
+}
+
+/* -------------------------------------------------------------------------
+ * Mixer stuff
+ */
+static void
+waveartist_mixer_update(wavnc_info *devc, int whichDev)
+{
+ unsigned int mask, reg_l, reg_r;
+ unsigned int lev_left, lev_right;
+ unsigned int vals[3];
+
+ lev_left = devc->levels[whichDev] & 0xff;
+ lev_right = devc->levels[whichDev] >> 8;
+
+#define SCALE(lev,max) ((lev) * (max) / 100)
+
+ switch(whichDev) {
+ case SOUND_MIXER_VOLUME:
+ mask = 0x000e;
+ reg_l = 0x200;
+ reg_r = 0x600;
+ lev_left = SCALE(lev_left, 7) << 1;
+ lev_right = SCALE(lev_right, 7) << 1;
+ break;
+
+ case SOUND_MIXER_LINE:
+ mask = 0x07c0;
+ reg_l = 0x000;
+ reg_r = 0x400;
+ lev_left = SCALE(lev_left, 31) << 6;
+ lev_right = SCALE(lev_right, 31) << 6;
+ break;
+
+ case SOUND_MIXER_MIC:
+ mask = 0x0030;
+ reg_l = 0x200;
+ reg_r = 0x600;
+ lev_left = SCALE(lev_left, 3) << 4;
+ lev_right = SCALE(lev_right, 3) << 4;
+ break;
+
+ case SOUND_MIXER_RECLEV:
+ mask = 0x000f;
+ reg_l = 0x300;
+ reg_r = 0x700;
+ lev_left = SCALE(lev_left, 10);
+ lev_right = SCALE(lev_right, 10);
+ break;
+
+ case SOUND_MIXER_LINE1:
+ mask = 0x003e;
+ reg_l = 0x000;
+ reg_r = 0x400;
+ lev_left = SCALE(lev_left, 31) << 1;
+ lev_right = SCALE(lev_right, 31) << 1;
+ break;
+
+ case SOUND_MIXER_PCM:
+ waveartist_cmd3(devc, 0x0031, SCALE(lev_left, 32767),
+ SCALE(lev_right, 32767));
+ return;
+
+ case SOUND_MIXER_SYNTH:
+ waveartist_cmd3(devc, 0x0131, SCALE(lev_left, 32767),
+ SCALE(lev_right, 32767));
+ return;
+
+ default:
+ return;
+ }
+
+ /* read left setting */
+ vals[0] = reg_l + 0x30;
+ waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+ /* read right setting */
+ vals[0] = reg_r + 0x30;
+ waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+ vals[1] = (vals[1] & ~mask) | (lev_left & mask);
+ vals[2] = (vals[2] & ~mask) | (lev_right & mask);
+
+ /* write left,right back */
+ vals[0] = 0x32;
+ waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static void
+waveartist_select_input(wavnc_info *devc, unsigned int input)
+{
+ unsigned int vals[3];
+#if 1
+ /* New mixer programming - switch recording source
+ * using R/L_ADC_Mux_Select. We are playing with
+ * left/right mux bit fields in reg 9.
+ *
+ * We can not switch Mux_Select while recording, so
+ * for microphones, enable both left and right and
+ * play with levels only!
+ *
+ * Unfortunately, we need to select the src of mono
+ * recording (left or right) before starting the
+ * recording - so can not dynamically switch between
+ * handset amd internal microphones...
+ */
+
+ /*
+ * Get reg 9
+ */
+ vals[0] = 0x0830;
+ waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+ /*
+ * Get reg 10, only so that we can write it back.
+ */
+ vals[0] = 0x0930;
+ waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n",
+ vals[1] & 0x07, (vals[1] >> 3) & 0x07);
+
+ vals[1] &= ~0x03F; //kill current left/right mux input select
+
+ switch (input) {
+ /*
+ * Handset or internal MIC
+ */
+ case SOUND_MASK_MIC:
+ /*
+ * handset not plugged in?
+ */
+ if (devc->handset_state & VNC_INTERNAL_MIC) {
+ /*
+ * set mono recording from right mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0134);
+#if 0
+ /*
+ * right=mic, left=none
+ */
+ vals[1] |= 0x0028;
+ /*
+ * pretend int mic
+ */
+ devc->rec_devices |= SOUND_MASK_SPEAKER;
+#endif
+ } else {
+ /*
+ * set mono rec from left mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+#if 0
+ /*
+ * right=none, left=mic
+ */
+ vals[1] |= 0x0005;
+ /*
+ * show no int mic
+ */
+ devc->rec_devices &= ~SOUND_MASK_SPEAKER;
+#endif
+ }
+ /*
+ * right=mic, left=mic
+ */
+ vals[1] |= 0x002D;
+ break;
+
+ case SOUND_MASK_LINE1:
+ /*
+ * set mono rec from left aux1
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * right=none, left=Aux1;
+ */
+ vals[1] |= 0x0004;
+ break;
+
+ case SOUND_MASK_LINE:
+ /*
+ * set mono rec from left (default)
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * right=Line, left=Line;
+ */
+ vals[1] |= 0x0012;
+ break;
+ }
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC %d: left=0x%04X, right=0x%04X.\n", input,
+ vals[1] & 0x07, (vals[1] >> 3) & 0x07);
+
+#else
+ /* This part is good, if input connected to
+ * a mixer, so can be used for record-only modes...
+ */
+
+ /*
+ * get reg 4
+ */
+ vals[0] = 0x0330;
+ waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+ /*
+ * get reg 8
+ */
+ vals[0] = 0x0730;
+ waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n",
+ vals[1], vals[2]);
+
+ /*
+ * kill current left/right mux input select
+ */
+ vals[1] &= ~0x07F8;
+ vals[2] &= ~0x07F8;
+
+ switch (input) {
+ /*
+ * handset or internal mic
+ */
+ case SOUND_MASK_MIC:
+ /*
+ * handset not plugged in?
+ */
+ if (devc->handset_state & VNC_INTERNAL_MIC) {
+ /*
+ * set mono recording from right mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0134);
+ /*
+ * left = none, right = mic, RX filter gain
+ */
+ vals[1] |= 0x0C00;
+ vals[2] |= 0x0C88;
+ /*
+ * pretend int mic
+ */
+ devc->rec_devices |= SOUND_MASK_SPEAKER;
+ } else {
+ /*
+ * set mono rec from left mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * left = mic, RX filter gain, right = none;
+ */
+ vals[1] |= 0x0C88;
+ vals[2] |= 0x0C00;
+ /*
+ * show no int mic
+ */
+ devc->rec_devices &= ~SOUND_MASK_SPEAKER;
+ }
+ break;
+
+ case SOUND_MASK_LINE1:
+ /*
+ * set mono rec from left aux1
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * left = Aux1, right = none
+ */
+ vals[1] |= 0x0C40;
+ vals[2] |= 0x0C00;
+ break;
+
+ case SOUND_MASK_LINE:
+ /*
+ * left = Line, right = Line
+ */
+ vals[1] |= 0x0C10;
+ vals[2] |= 0x0C10;
+ break;
+ }
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC %d: left(4) 0x%04X, right(8) 0x%04X.\n",
+ level, vals[1], vals[2]);
+#endif
+ /*
+ * and finally - write the reg pair back....
+ */
+ vals[0] = 0x32;
+
+ waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static int
+waveartist_mixer_set(wavnc_info *devc, int whichDev, unsigned int level)
+{
+ unsigned int lev_left = level & 0x007f;
+ unsigned int lev_right = (level & 0x7f00) >> 8;
+
+ int left, right, devmask, changed, i;
+
+ left = level & 0x7f;
+ right = (level & 0x7f00) >> 8;
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("wa_mixer_set(dev=%d, level=%X)\n",
+ whichDev, level);
+
+ switch (whichDev) {
+ /* Master volume (0-7)
+ * We have 3 bits on the Left/Right Mixer Gain,
+ * bits 3,2,1 on 3 and 7
+ */
+ case SOUND_MIXER_VOLUME:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+
+ /* External line (0-31)
+ * use LOUT/ROUT bits 10...6, reg 1 and 5
+ */
+ case SOUND_MIXER_LINE:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Mono microphone (0-3) mute,
+ * 0db,10db,20db
+ */
+ case SOUND_MIXER_MIC:
+#if 1
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+#else
+ /* we do not need to mute volume of
+ * an unused mic - it is simply unused...
+ */
+ if (devc->handset_state & VNC_INTERNAL_MIC)
+ devc->levels[whichDev] = lev_right << 8;
+ else
+ levels[whichDev] = lev_left;
+#endif
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Recording level (0-7)
+ */
+ case SOUND_MIXER_RECLEV:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Mono External Aux1 (0-31)
+ * use LINE1 bits 5...1, reg 1 and 5
+ */
+ case SOUND_MIXER_LINE1:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* WaveArtist PCM (0-32767)
+ */
+ case SOUND_MIXER_PCM:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Internal synthesizer (0-31)
+ */
+ case SOUND_MIXER_SYNTH:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+
+ /* Select recording input source
+ */
+ case SOUND_MIXER_RECSRC:
+ devmask = level & POSSIBLE_RECORDING_DEVICES;
+
+ changed = devmask ^ devc->recmask;
+ devc->recmask = devmask;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (changed & (1 << i))
+ waveartist_mixer_update(devc, i);
+
+ waveartist_select_input(devc, level);
+ /*
+ * do not save in "levels", return current setting
+ */
+ return devc->recmask;
+
+ default:
+ return -EINVAL;
+ }
+
+ return devc->levels[whichDev];
+}
+
+static void
+waveartist_mixer_reset(wavnc_info *devc)
+{
+ int i;
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("%s: mixer_reset\n", devc->hw.name);
+
+ /*
+ * reset mixer cmd
+ */
+ waveartist_sendcmd(&devc->hw, 0x33);
+
+ /*
+ * set input for ADC to come from
+ * a mux (left and right) == reg 9,
+ * initially none
+ */
+ waveartist_cmd3(devc, 0x0032, 0x9800, 0xa836);
+
+ /*
+ * set mixer input select to none, RX filter gains 0 db
+ */
+ waveartist_cmd3(devc, 0x0032, 0x4c00, 0x8c00);
+
+ /*
+ * set bit 0 reg 2 to 1 - unmute MonoOut
+ */
+ waveartist_cmd3(devc, 0x0032, 0x2801, 0x6800);
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ waveartist_mixer_update(devc, i);
+
+ /* set default input device = internal mic
+ * current recording device = none
+ * no handset
+ */
+ devc->recmask = 0;
+ devc->handset_state = VNC_INTERNAL_MIC;
+// waveartist_mixer_set(devc, SOUND_MIXER_RECSRC, SOUND_MASK_MIC);
+
+ /*
+ * start from enabling the hw setting
+ */
+ devc->handset_mute_sw = 0;
+ devc->supported_devices = SUPPORTED_MIXER_DEVICES;
+ devc->rec_devices = POSSIBLE_RECORDING_DEVICES;
+}
+
+static int
+waveartist_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+ wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc;
+#if 0
+ //use this call to override the automatic handset behaviour - ignore handset
+ //bit 0x80 = total control over handset - do not react to plug/unplug
+ //bit 0x10 = 1 == internal mic, otherwise handset mic
+ //bit 0x01 = 1 == mute internal speaker, otherwise unmute
+
+ if (cmd == SOUND_MIXER_PRIVATE1) {
+ int val, temp;
+
+ val = *(int *) arg;
+
+// printk("MIXER_PRIVATE1: passed parameter = 0x%X.\n",val);
+ return -EINVAL; //check if parameter is logical...
+
+ devc->soft_mute_flag = val;
+
+ temp = val & VNC_INTERNAL_SPKR;
+ if (temp != devc->mute_state) {
+// printk("MIXER_PRIVATE1: mute_mono(0x%X).\n",temp);
+ vnc_mute(devc, temp);
+ }
+
+// temp = devc->handset_state;
+
+ // do not check if it is not already in
+ // the right setting, since we are
+ // laying about the current state...
+
+// if ((val & VNC_INTERNAL_MIC) != temp) {
+ devc->handset_state = val & VNC_INTERNAL_MIC;
+// printk("MIXER_PRIVATE1: mixer_set(0x%X).\n",devc->handset_state);
+ wa_mixer_set(devc, SOUND_MIXER_RECSRC, SOUND_MASK_MIC);
+// devc->handset_state = temp;
+ }
+ return 0;
+ }
+#if 0
+ if (cmd == SOUND_MIXER_PRIVATE2) {
+#define VNC_SOUND_PAUSE 0x53 //to pause the DSP
+#define VNC_SOUND_RESUME 0x57 //to unpause the DSP
+ int val;
+
+ val = *(int *) arg;
+
+ printk("MIXER_PRIVATE2: passed parameter = 0x%X.\n",val);
+
+ if (val == VNC_SOUND_PAUSE) {
+ wa_sendcmd(0x16); //PAUSE the ADC
+ } else if (val == VNC_SOUND_RESUME) {
+ wa_sendcmd(0x18); //RESUME the ADC
+ } else {
+ return -EINVAL; //invalid parameters...
+ }
+ return 0;
+ }
+#endif
+
+ if (cmd == SOUND_MIXER_PRIVATE3) {
+ long unsigned flags;
+ int mixer_reg[15]; //reg 14 is actually a command: read,write,reset
+
+ int val;
+ int i;
+
+ val = *(int *) arg;
+
+ if (verify_area(VERIFY_READ, (void *) val, sizeof(mixer_reg) == -EFAULT))
+ return (-EFAULT);
+
+ memcpy_fromfs(&mixer_reg, (void *) val, sizeof(mixer_reg));
+
+ if (mixer_reg[0x0E] == MIXER_PRIVATE3_RESET) { //reset command??
+ wavnc_mixer_reset(devc);
+ return (0);
+ } else if (mixer_reg[0x0E] == MIXER_PRIVATE3_WRITE) { //write command??
+// printk("WaveArtist Mixer: Private write command.\n");
+
+ wa_sendcmd(0x32); //Pair1 - word 1 and 5
+ wa_sendcmd(mixer_reg[0]);
+ wa_sendcmd(mixer_reg[4]);
+
+ wa_sendcmd(0x32); //Pair2 - word 2 and 6
+ wa_sendcmd(mixer_reg[1]);
+ wa_sendcmd(mixer_reg[5]);
+
+ wa_sendcmd(0x32); //Pair3 - word 3 and 7
+ wa_sendcmd(mixer_reg[2]);
+ wa_sendcmd(mixer_reg[6]);
+
+ wa_sendcmd(0x32); //Pair4 - word 4 and 8
+ wa_sendcmd(mixer_reg[3]);
+ wa_sendcmd(mixer_reg[7]);
+
+ wa_sendcmd(0x32); //Pair5 - word 9 and 10
+ wa_sendcmd(mixer_reg[8]);
+ wa_sendcmd(mixer_reg[9]);
+
+ wa_sendcmd(0x0031); //set left and right PCM
+ wa_sendcmd(mixer_reg[0x0A]);
+ wa_sendcmd(mixer_reg[0x0B]);
+
+ wa_sendcmd(0x0131); //set left and right FM
+ wa_sendcmd(mixer_reg[0x0C]);
+ wa_sendcmd(mixer_reg[0x0D]);
+
+ return 0;
+ } else if (mixer_reg[0x0E] == MIXER_PRIVATE3_READ) { //read command?
+// printk("WaveArtist Mixer: Private read command.\n");
+
+ //first read all current values...
+ save_flags(flags);
+ cli();
+
+ for (i = 0; i < 14; i++) {
+ wa_sendcmd((i << 8) + 0x30); // get ready for command nn30H
+
+ while (!(inb(STATR) & CMD_RF)) {
+ }; //wait for response ready...
+
+ mixer_reg[i] = inw(CMDR);
+ }
+ restore_flags(flags);
+
+ if (verify_area(VERIFY_WRITE, (void *) val, sizeof(mixer_reg) == -EFAULT))
+ return (-EFAULT);
+
+ memcpy_tofs((void *) val, &mixer_reg, sizeof(mixer_reg));
+ return 0;
+ } else
+ return -EINVAL;
+ }
+#endif
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
+ int val;
+
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+
+ /*
+ * special case for master volume: if we
+ * received this call - switch from hw
+ * volume control to a software volume
+ * control, till the hw volume is modified
+ * to signal that user wants to be back in
+ * hardware...
+ */
+ if ((cmd & 0xff) == SOUND_MIXER_VOLUME)
+ devc->use_slider = 0;
+
+ return waveartist_mixer_set(devc, cmd & 0xff, val);
+ } else {
+ int ret;
+
+ /*
+ * Return parameters
+ */
+ switch (cmd & 0xff) {
+ case SOUND_MIXER_RECSRC:
+ ret = devc->recmask;
+
+ if (devc->handset_state & VNC_INTERNAL_MIC)
+ ret |= SOUND_MASK_SPEAKER;
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ ret = devc->supported_devices;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ ret = devc->supported_devices &
+ ~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ ret = devc->rec_devices;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ ret = SOUND_CAP_EXCL_INPUT;
+ break;
+
+ default:
+ if ((cmd & 0xff) < SOUND_MIXER_NRDEVICES)
+ ret = devc->levels[cmd & 0xff];
+ else
+ return -EINVAL;
+ }
+
+ return put_user(ret, (int *)arg) ? -EINVAL : 0;
+ }
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static struct mixer_operations waveartist_mixer_operations =
+{
+ "WaveArtist",
+ "WaveArtist NetWinder",
+ waveartist_mixer_ioctl
+};
+
+static int
+waveartist_init(wavnc_info *devc)
+{
+ wavnc_port_info *portc;
+ char rev[3], dev_name[64];
+ int my_dev;
+
+ waveartist_reset(devc);
+
+ sprintf(dev_name, "%s (%s", devc->hw.name, devc->chip_name);
+
+ if (waveartist_getrev(&devc->hw, rev)) {
+ strcat(dev_name, " rev. ");
+ strcat(dev_name, rev);
+ }
+ strcat(dev_name, ")");
+
+ conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
+ devc->hw.dma, devc->hw.dma2);
+
+ portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+ if (portc == NULL)
+ goto nomem;
+
+ memset(portc, 0, sizeof(wavnc_port_info));
+
+ my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,
+ &waveartist_audio_driver, sizeof(struct audio_driver),
+ devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,
+ devc, devc->hw.dma, devc->hw.dma2);
+
+ if (my_dev < 0)
+ goto free;
+
+ audio_devs[my_dev]->portc = portc;
+
+ waveartist_mixer_reset(devc);
+
+ /*
+ * clear any pending interrupt
+ */
+ waveartist_iack(devc);
+
+ if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) {
+ printk("%s: IRQ %d in use\n",
+ devc->hw.name, devc->hw.irq);
+ goto uninstall;
+ }
+
+ if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) {
+ printk("%s: Can't allocate DMA%d\n",
+ devc->hw.name, devc->hw.dma);
+ goto uninstall_irq;
+ }
+
+ if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA)
+ if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) {
+ printk("%s: can't allocate DMA%d\n",
+ devc->hw.name, devc->hw.dma2);
+ goto uninstall_dma;
+ }
+
+ waveartist_set_ctlr(&devc->hw, 0, DMA1_IE | DMA0_IE);
+
+ audio_devs[my_dev]->mixer_dev =
+ sound_install_mixer(MIXER_DRIVER_VERSION,
+ dev_name,
+ &waveartist_mixer_operations,
+ sizeof(struct mixer_operations),
+ devc);
+
+ return my_dev;
+
+uninstall_dma:
+ sound_free_dma(devc->hw.dma);
+
+uninstall_irq:
+ free_irq(devc->hw.irq, devc);
+
+uninstall:
+ sound_unload_audiodev(my_dev);
+
+free:
+ kfree(portc);
+
+nomem:
+ return -1;
+}
+
+/*
+ * Corel Netwinder specifics...
+ */
+static void
+vnc_mute(wavnc_info *devc, int mute)
+{
+ extern spinlock_t gpio_lock;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ cpld_modify(CPLD_UNMUTE, mute ? 0 : CPLD_UNMUTE);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ devc->mute_state = mute;
+}
+
+static int
+vnc_volume_slider(wavnc_info *devc)
+{
+ static signed int old_slider_volume;
+ unsigned long flags;
+ signed int volume = 255;
+
+ *CSR_TIMER1_LOAD = 0x00ffffff;
+
+ save_flags(flags);
+ cli();
+
+ outb(0xFF, 0x201);
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV1;
+
+ while (volume && (inb(0x201) & 0x01))
+ volume--;
+
+ *CSR_TIMER1_CNTL = 0;
+
+ restore_flags(flags);
+
+ volume = 0x00ffffff - *CSR_TIMER1_VALUE;
+
+
+#ifndef REVERSE
+ volume = 150 - (volume >> 5);
+#else
+ volume = (volume >> 6) - 25;
+#endif
+
+ if (volume < 0)
+ volume = 0;
+
+ if (volume > 100)
+ volume = 100;
+
+ /*
+ * slider quite often reads +-8, so debounce this random noise
+ */
+ if ((volume - old_slider_volume) > 7 ||
+ (old_slider_volume - volume) > 7) {
+ old_slider_volume = volume;
+
+ DEB(printk("Slider volume: %d.\n", old_slider_volume));
+ }
+
+ return old_slider_volume;
+}
+
+static int
+vnc_slider(wavnc_info *devc)
+{
+ signed int slider_volume;
+ unsigned int temp;
+
+ /*
+ * read the "buttons" state.
+ * Bit 4 = handset present,
+ * Bit 5 = offhook
+ */
+ // the state should be "querable" via a private IOCTL call
+ temp = inb(0x201) & 0x30;
+
+ if (!devc->handset_mute_sw &&
+ (temp ^ devc->handset_state) & VNC_INTERNAL_MIC) {
+ devc->handset_state = temp;
+ devc->handset_mute_sw = 0;
+
+ vnc_mute(devc, (temp & VNC_INTERNAL_MIC) ? 1 : 0);
+ }
+
+ slider_volume = vnc_volume_slider(devc);
+
+ /*
+ * If we're using software controlled volume, and
+ * the slider moves by more than 20%, then we
+ * switch back to slider controlled volume.
+ */
+ if (devc->slider_vol > slider_volume) {
+ if (devc->slider_vol - slider_volume > 20)
+ devc->use_slider = 1;
+ } else {
+ if (slider_volume - devc->slider_vol > 20)
+ devc->use_slider = 1;
+ }
+
+ /*
+ * use only left channel
+ */
+ temp = levels[SOUND_MIXER_VOLUME] & 0xFF;
+
+ if (slider_volume != temp && devc->use_slider) {
+ devc->slider_vol = slider_volume;
+
+ waveartist_mixer_set(devc, SOUND_MIXER_VOLUME,
+ slider_volume | slider_volume << 8);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+vnc_slider_tick(unsigned long data)
+{
+ int next_timeout;
+
+ if (vnc_slider(adev_info + data))
+ next_timeout = 5; // mixer reported change
+ else
+ next_timeout = VNC_TIMER_PERIOD;
+
+ mod_timer(&vnc_timer, jiffies + next_timeout);
+}
+
+int
+probe_waveartist(struct address_info *hw_config)
+{
+ wavnc_info *devc = &adev_info[nr_waveartist_devs];
+
+ if (nr_waveartist_devs >= MAX_AUDIO_DEV) {
+ printk("waveartist: too many audio devices\n");
+ return 0;
+ }
+
+ if (check_region(hw_config->io_base, 15)) {
+ printk("WaveArtist: I/O port conflict\n");
+ return 0;
+ }
+
+ if (hw_config->irq > 31 || hw_config->irq < 16) {
+ printk("WaveArtist: Bad IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+
+ if (hw_config->dma != 3) {
+ printk("WaveArtist: Bad DMA %d\n", hw_config->dma);
+ return 0;
+ }
+
+ hw_config->name = "WaveArtist";
+ devc->hw = *hw_config;
+ devc->open_mode = 0;
+ devc->chip_name = "RWA-010";
+
+ return 1;
+}
+
+void
+attach_waveartist(struct address_info *hw)
+{
+ wavnc_info *devc = &adev_info[nr_waveartist_devs];
+
+ /*
+ * NOTE! If irq < 0, there is another driver which has allocated the
+ * IRQ so that this driver doesn't need to allocate/deallocate it.
+ * The actually used IRQ is ABS(irq).
+ */
+ devc->hw = *hw;
+ devc->hw.irq = (hw->irq > 0) ? hw->irq : 0;
+ devc->open_mode = 0;
+ devc->playback_dev = 0;
+ devc->record_dev = 0;
+ devc->audio_flags = DMA_AUTOMODE;
+ devc->levels = levels;
+
+ if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)
+ devc->audio_flags |= DMA_DUPLEX;
+
+ request_region(hw->io_base, 15, devc->hw.name);
+
+ devc->dev_no = waveartist_init(devc);
+
+ if (devc->dev_no < 0)
+ release_region(hw->io_base, 15);
+ else {
+ init_timer(&vnc_timer);
+ vnc_timer.function = vnc_slider_tick;
+ vnc_timer.expires = jiffies;
+ vnc_timer.data = nr_waveartist_devs;
+ add_timer(&vnc_timer);
+
+ nr_waveartist_devs += 1;
+
+ vnc_mute(devc, 0);
+ }
+}
+
+void
+unload_waveartist(struct address_info *hw)
+{
+ wavnc_info *devc = NULL;
+ int i;
+
+ for (i = 0; i < nr_waveartist_devs; i++)
+ if (hw->io_base == adev_info[i].hw.io_base) {
+ devc = adev_info + i;
+ break;
+ }
+
+ if (devc != NULL) {
+ int mixer;
+
+ release_region(devc->hw.io_base, 15);
+
+ waveartist_set_ctlr(&devc->hw, DMA1_IE|DMA0_IE, 0);
+
+ if (devc->hw.irq >= 0)
+ free_irq(devc->hw.irq, devc);
+
+ sound_free_dma(devc->hw.dma);
+
+ if (devc->hw.dma != devc->hw.dma2 &&
+ devc->hw.dma2 != NO_DMA)
+ sound_free_dma(devc->hw.dma2);
+
+ del_timer(&vnc_timer);
+
+ mixer = audio_devs[devc->dev_no]->mixer_dev;
+
+ if (mixer >= 0)
+ sound_unload_mixerdev(mixer);
+
+ if (devc->dev_no >= 0)
+ sound_unload_audiodev(devc->dev_no);
+
+ nr_waveartist_devs -= 1;
+
+ for (; i < nr_waveartist_devs; i++)
+ adev_info[i] = adev_info[i + 1];
+ } else
+ printk("waveartist: can't find device to unload\n");
+}
+
+#ifdef MODULE
+
+MODULE_PARM(io, "i"); /* IO base */
+MODULE_PARM(irq, "i"); /* IRQ */
+MODULE_PARM(dma, "i"); /* DMA */
+MODULE_PARM(dma2, "i"); /* DMA2 */
+
+int io = CONFIG_WAVEARTIST_BASE;
+int irq = CONFIG_WAVEARTIST_IRQ;
+int dma = CONFIG_WAVEARTIST_DMA;
+int dma2 = CONFIG_WAVEARTIST_DMA2;
+
+static int attached;
+
+struct address_info hw_config;
+
+int init_module(void)
+{
+ hw_config.io_base = io;
+ hw_config.irq = irq;
+ hw_config.dma = dma;
+ hw_config.dma2 = dma2;
+
+ if (!probe_waveartist(&hw_config))
+ return -ENODEV;
+
+ attach_waveartist(&hw_config);
+ attached = 1;
+
+ SOUND_LOCK;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (attached) {
+ SOUND_LOCK_END;
+
+ unload_waveartist(&hw_config);
+ }
+}
+#endif
diff --git a/drivers/sound/waveartist.h b/drivers/sound/waveartist.h
new file mode 100644
index 000000000..360bc95f1
--- /dev/null
+++ b/drivers/sound/waveartist.h
@@ -0,0 +1,68 @@
+
+// def file for Rockwell RWA010 chip set, as installed in Corel NetWinder
+
+//registers
+#define WA_BASE 0
+//x250
+
+#define CMDR WA_BASE+0
+#define DATR WA_BASE+2
+
+#define CTLR WA_BASE+4
+#define STATR WA_BASE+5
+
+#define IRQSTAT WA_BASE+12
+
+//bit defs
+//reg STATR
+#define CMD_WE 0x80
+#define CMD_RF 0x40
+#define DAT_WE 0x20
+#define DAT_RF 0x10
+
+#define IRQ_REQ 0x08
+#define DMA1 0x04
+#define DMA0 0x02
+
+//bit defs
+//reg CTLR
+#define CMD_WEIE 0x80
+#define CMD_RFIE 0x40
+#define DAT_WEIE 0x20
+#define DAT_RFIE 0x10
+
+#define RESET 0x08
+#define DMA1_IE 0x04
+#define DMA0_IE 0x02
+#define IRQ_ACK 0x01
+
+//commands
+
+#define WACMD_SYSTEMID 0
+#define WACMD_INPUTFORMAT 0x10 //0-8S, 1-16S, 2-8U
+#define WACMD_INPUTCHANNELS 0x11 //1-Mono, 2-Stereo
+#define WACMD_INPUTSPEED 0x12 //sampling rate
+#define WACMD_INPUTDMA 0x13 //0-8bit, 1-16bit, 2-PIO
+#define WACMD_INPUTSIZE 0x14 //samples to interrupt
+#define WACMD_INPUTSTART 0x15 //start ADC
+#define WACMD_INPUTPAUSE 0x16 //pause ADC
+#define WACMD_INPUTSTOP 0x17 //stop ADC
+#define WACMD_INPUTRESUME 0x18 //resume ADC
+#define WACMD_INPUTPIO 0x19 //PIO ADC
+
+#define WACMD_OUTPUTFORMAT 0x20 //0-8S, 1-16S, 2-8U
+#define WACMD_OUTPUTCHANNELS 0x21 //1-Mono, 2-Stereo
+#define WACMD_OUTPUTSPEED 0x22 //sampling rate
+#define WACMD_OUTPUTDMA 0x23 //0-8bit, 1-16bit, 2-PIO
+#define WACMD_OUTPUTSIZE 0x24 //samples to interrupt
+#define WACMD_OUTPUTSTART 0x25 //start ADC
+#define WACMD_OUTPUTPAUSE 0x26 //pause ADC
+#define WACMD_OUTPUTSTOP 0x27 //stop ADC
+#define WACMD_OUTPUTRESUME 0x28 //resume ADC
+#define WACMD_OUTPUTPIO 0x29 //PIO ADC
+
+
+
+
+int wa_sendcmd(unsigned int cmd);
+int wa_writecmd(unsigned int cmd, unsigned int arg);
diff --git a/drivers/sound/wavfront.c b/drivers/sound/wavfront.c
index b2e33ab1a..b6ec7c263 100644
--- a/drivers/sound/wavfront.c
+++ b/drivers/sound/wavfront.c
@@ -22,10 +22,17 @@
* now, you just get the YSS225 in the same state as Turtle Beach's
* "SETUPSND.EXE" utility leaves it.
*
- * The boards' CODEC (a Crystal CS4232) is supported by cs4232.[co],
+ * The boards' DAC/ADC (a Crystal CS4232) is supported by cs4232.[co],
* This chip also controls the configuration of the card: the wavefront
* synth is logical unit 4.
*
+ *
+ * Supported devices:
+ *
+ * /dev/dsp - using cs4232+ad1848 modules, OSS compatible
+ * /dev/midiNN and /dev/midiNN+1 - using wf_midi code, OSS compatible
+ * /dev/synth00 - raw synth interface
+ *
**********************************************************************
*
* Copyright (C) by Paul Barton-Davis 1998
@@ -36,9 +43,9 @@
* Although the relevant code here is all new, the handling of
* sample/alias/multi- samples is entirely based on a driver by Matt
* Martin and Rutger Nijlunsing which demonstrated how to get things
- * to most aspects of this to work correctly. The GUS patch loading
- * code has been almost unaltered by me, except to fit formatting and
- * function names in the rest of the file. Many thanks to them.
+ * to work correctly. The GUS patch loading code has been almost
+ * unaltered by me, except to fit formatting and function names in the
+ * rest of the file. Many thanks to them.
*
* Appreciation and thanks to Hannu Savolainen for his early work on the Maui
* driver, and answering a few questions while this one was developed.
@@ -49,27 +56,79 @@
* aspects of configuring a WaveFront soundcard, particularly the
* effects processor.
*
- * $Id: wavfront.c,v 0.5 1998/07/22 16:16:41 pbd Exp $
+ * $Id: wavfront.c,v 0.7 1998/09/09 15:47:36 pbd Exp $
*
* This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
- */
+ * for more info. */
-#include <linux/config.h>
#include <linux/module.h>
-#include <asm/init.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/fcntl.h>
+#include <linux/ioport.h>
+
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/delay.h>
#include "sound_config.h"
#include "soundmodule.h"
#include <linux/wavefront.h>
+/*
+ * This sucks, hopefully it'll get standardised
+ */
+
+#if defined(__alpha__)
+#ifdef __SMP__
+#define LOOPS_PER_SEC cpu_data[smp_processor_id()].loops_per_sec
+#else
+#define LOOPS_PER_SEC loops_per_sec
+#endif
+#endif
+
+#if defined(__i386__)
+#define LOOPS_PER_SEC current_cpu_data.loops_per_sec
+#endif
+
+#define _MIDI_SYNTH_C_
#define MIDI_SYNTH_NAME "WaveFront MIDI"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include "midi_synth.h"
-/* This thing is meant to work as a module */
+/* Compile-time control of the extent to which OSS is supported.
+
+ I consider /dev/sequencer to be an anachronism, but given its
+ widespread usage by various Linux MIDI software, it seems worth
+ offering support to it if its not too painful. Instead of using
+ /dev/sequencer, I recommend:
+
+ for synth programming and patch loading: /dev/synthNN
+ for kernel-synchronized MIDI sequencing: the ALSA sequencer
+ for direct MIDI control: /dev/midiNN
+
+ I have never tried static compilation into the kernel. The #if's
+ for this are really just notes to myself about what the code is
+ for.
+*/
+
+#define OSS_SUPPORT_SEQ 0x1 /* use of /dev/sequencer */
+#define OSS_SUPPORT_STATIC_INSTALL 0x2 /* static compilation into kernel */
+
+#define OSS_SUPPORT_LEVEL 0x1 /* just /dev/sequencer for now */
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+static int (*midi_load_patch) (int devno, int format, const char *addr,
+ int offs, int count, int pmgr_flag) = NULL;
+#endif OSS_SUPPORT_SEQ
+
+/* This is meant to work as a module */
#if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE)
@@ -81,14 +140,28 @@
#define WF_DEBUG 1
+#ifdef WF_DEBUG
+
+/* Thank goodness for gcc's preprocessor ... */
+
+#define DPRINT(cond, format, args...) \
+ if ((dev.debug & (cond)) == (cond)) { \
+ printk (KERN_DEBUG LOGNAME format, ## args); \
+ }
+#else
+#define DPRINT(cond, format, args...)
+#endif
+
+#define LOGNAME "WaveFront: "
+
/* bitmasks for WaveFront status port value */
-#define STAT_INTR_WRITE 0x40
-#define STAT_CAN_WRITE 0x20
-#define STAT_WINTR_ENABLED 0x10
-#define STAT_INTR_READ 0x04
-#define STAT_CAN_READ 0x02
#define STAT_RINTR_ENABLED 0x01
+#define STAT_CAN_READ 0x02
+#define STAT_INTR_READ 0x04
+#define STAT_WINTR_ENABLED 0x10
+#define STAT_CAN_WRITE 0x20
+#define STAT_INTR_WRITE 0x40
/*** Module-accessible parameters ***************************************/
@@ -117,9 +190,6 @@ char *ospath = "/etc/sound/wavefront.os"; /* where to find a processed
version of the WaveFront OS
*/
-int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */
-int sleep_tries = 50; /* number of times we'll try to sleep */
-
int wait_usecs = 150; /* This magic number seems to give pretty optimal
throughput based on my limited experimentation.
If you want to play around with it and find a better
@@ -133,24 +203,40 @@ int wait_usecs = 150; /* This magic number seems to give pretty optimal
status waits, only about 250 result in a sleep.
*/
+int sleep_interval = 100; /* HZ/sleep_interval seconds per sleep */
+int sleep_tries = 50; /* number of times we'll try to sleep */
+
+int reset_time = 2; /* hundreths of a second we wait after a HW reset for
+ the expected interrupt.
+ */
+
+int ramcheck_time = 20; /* time in seconds to wait while ROM code
+ checks on-board RAM.
+ */
+
+int osrun_time = 10; /* time in seconds we wait for the OS to
+ start running.
+ */
+
MODULE_PARM(wf_raw,"i");
MODULE_PARM(fx_raw,"i");
MODULE_PARM(debug_default,"i");
+MODULE_PARM(wait_usecs,"i");
MODULE_PARM(sleep_interval,"i");
MODULE_PARM(sleep_tries,"i");
-MODULE_PARM(wait_usecs,"i");
MODULE_PARM(ospath,"s");
+MODULE_PARM(reset_time,"i");
+MODULE_PARM(ramcheck_time,"i");
+MODULE_PARM(osrun_time,"i");
/***************************************************************************/
-static struct synth_info wavefront_info =
-{"Turtle Beach WaveFront", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_WAVEFRONT,
- 0, 32, 0, 0, SYNTH_CAP_INPUT};
-
-static int (*midi_load_patch) (int dev, int format, const char *addr,
- int offs, int count, int pmgr_flag) = NULL;
+/* Note: because this module doesn't export any symbols, this really isn't
+ a global variable, even if it looks like one. I was quite confused by
+ this when I started writing this as a (newer) module -- pbd.
+*/
-typedef struct wf_config {
+struct wf_config {
int devno; /* device number from kernel */
int irq; /* "you were one, one of the few ..." */
int base; /* low i/o port address */
@@ -181,15 +267,23 @@ typedef struct wf_config {
#define fx_mod_data base + 0xf
volatile int irq_ok; /* set by interrupt handler */
- int opened; /* flag, holds open(1) mode */
+ volatile int irq_cnt; /* ditto */
+ int opened; /* flag, holds open(2) mode */
char debug; /* debugging flags */
int freemem; /* installed RAM, in bytes */
- int synthdev; /* OSS minor devnum for synth */
- int mididev; /* OSS minor devno for internal MIDI */
- int ext_mididev; /* OSS minor devno for external MIDI */
+
+ int synth_dev; /* devno for "raw" synth */
+ int mididev; /* devno for internal MIDI */
+ int ext_mididev; /* devno for external MIDI */
+ int fx_mididev; /* devno for FX MIDI interface */
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+ int oss_dev; /* devno for OSS sequencer synth */
+#endif OSS_SUPPORT_SEQ
+
char fw_version[2]; /* major = [0], minor = [1] */
char hw_version[2]; /* major = [0], minor = [1] */
char israw; /* needs Motorola microcode */
+ char has_fx; /* has FX processor (Tropez+) */
char prog_status[WF_MAX_PROGRAM]; /* WF_SLOT_* */
char patch_status[WF_MAX_PATCH]; /* WF_SLOT_* */
char sample_status[WF_MAX_SAMPLE]; /* WF_ST_* | WF_SLOT_* */
@@ -197,27 +291,22 @@ typedef struct wf_config {
char interrupts_on; /* h/w MPU interrupts enabled ? */
char rom_samples_rdonly; /* can we write on ROM samples */
struct wait_queue *interrupt_sleeper;
-#ifdef WF_STATS
- unsigned long status_found_during_loop;
- unsigned long status_found_during_sleep[4];
-#endif WF_STATS
-
-} wf_config;
-
-/* Note: because this module doesn't export any symbols, this really isn't
- a global variable, even if it looks like one. I was quite confused by
- this when I started writing this as a (newer) module -- pbd.
-*/
+} dev;
-static wf_config wavefront_configuration;
+static int detect_wffx(void);
+static int wffx_ioctl (wavefront_fx_info *);
+static int wffx_init (void);
-#define wavefront_status(hw) (inb (hw->status_port))
+static int wavefront_delete_sample (int sampnum);
+static int wavefront_find_free_sample (void);
-/* forward references */
+/* From wf_midi.c */
-static int wffx_ioctl (struct wf_config *, wavefront_fx_info *);
-static int wffx_init (struct wf_config *hw);
-static int wavefront_delete_sample (struct wf_config *hw, int sampnum);
+extern int virtual_midi_enable (void);
+extern int virtual_midi_disable (void);
+extern int detect_wf_mpu (int, int);
+extern int install_wf_mpu (void);
+extern int uninstall_wf_mpu (void);
typedef struct {
int cmd;
@@ -339,92 +428,92 @@ wavefront_get_command (int cmd)
return (wavefront_command *) 0;
}
+static inline int
+wavefront_status (void)
+
+{
+ return inb (dev.status_port);
+}
+
static int
-wavefront_sleep (wf_config *hw, int limit)
+wavefront_sleep (int limit)
{
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(limit);
+
return signal_pending(current);
}
-
+
static int
-wavefront_wait (wf_config *hw, int mask)
+wavefront_wait (int mask)
{
int i;
static int short_loop_cnt = 0;
+ /* Compute the loop count that lets us sleep for about the
+ right amount of time, cache issues, bus speeds and all
+ other issues being unequal but largely irrelevant.
+ */
+
if (short_loop_cnt == 0) {
- short_loop_cnt = (int) (((double) wait_usecs / 1000000.0) *
- (double) current_cpu_data.loops_per_sec);
+ short_loop_cnt = wait_usecs *
+ (LOOPS_PER_SEC / 1000000);
}
+ /* Spin for a short period of time, because >99% of all
+ requests to the WaveFront can be serviced inline like this.
+ */
+
for (i = 0; i < short_loop_cnt; i++) {
- if (wavefront_status(hw) & mask) {
-#ifdef WF_STATS
- hw->status_found_during_loop++;
-#endif WF_STATS
+ if (wavefront_status() & mask) {
return 1;
}
}
for (i = 0; i < sleep_tries; i++) {
- if (wavefront_status(hw) & mask) {
-#ifdef WF_STATS
- if (i < 4) {
- hw->status_found_during_sleep[i]++;
- }
-#endif WF_STATS
+ if (wavefront_status() & mask) {
return 1;
}
- if (wavefront_sleep (hw, HZ/sleep_interval)) {
+ if (wavefront_sleep (HZ/sleep_interval)) {
return (0);
}
}
- return 0;
+ return (0);
}
static int
-wavefront_read (wf_config *hw)
+wavefront_read (void)
+
{
- if (wavefront_wait (hw, STAT_CAN_READ))
- return inb (hw->data_port);
+ if (wavefront_wait (STAT_CAN_READ))
+ return inb (dev.data_port);
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: read timeout.\n");
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_DATA, "read timeout.\n");
return -1;
}
static int
-wavefront_write (wf_config *hw, unsigned char data)
+wavefront_write (unsigned char data)
{
- if (wavefront_wait (hw, STAT_CAN_WRITE)) {
- outb (data, hw->data_port);
- return 1;
+ if (wavefront_wait (STAT_CAN_WRITE)) {
+ outb (data, dev.data_port);
+ return 0;
}
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: write timeout.\n");
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_DATA, "write timeout.\n");
- return 0;
+ return -1;
}
static int
-wavefront_cmd (wf_config *hw, int cmd,
- unsigned char *rbuf,
- unsigned char *wbuf)
+wavefront_cmd (int cmd, unsigned char *rbuf, unsigned char *wbuf)
{
int ack;
@@ -433,7 +522,7 @@ wavefront_cmd (wf_config *hw, int cmd,
wavefront_command *wfcmd;
if ((wfcmd = wavefront_get_command (cmd)) == (wavefront_command *) 0) {
- printk (KERN_WARNING "WaveFront: command 0x%x not supported.\n",
+ printk (KERN_WARNING LOGNAME "command 0x%x not supported.\n",
cmd);
return 1;
}
@@ -448,89 +537,59 @@ wavefront_cmd (wf_config *hw, int cmd,
rbuf = 0;
}
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_CMD) {
- printk (KERN_DEBUG "Wavefront: 0x%x [%s] (%d,%d,%d)\n",
- cmd, wfcmd->action, wfcmd->read_cnt, wfcmd->write_cnt,
- wfcmd->need_ack);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_CMD, "0x%x [%s] (%d,%d,%d)\n",
+ cmd, wfcmd->action, wfcmd->read_cnt,
+ wfcmd->write_cnt, wfcmd->need_ack);
- if (!wavefront_write (hw, cmd)) {
-#ifdef WF_DEBUG
- if (hw->debug & (WF_DEBUG_IO|WF_DEBUG_CMD)) {
- printk (KERN_DEBUG "WaveFront: cannot request "
- "0x%x [%s].\n",
- cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ if (wavefront_write (cmd)) {
+ DPRINT ((WF_DEBUG_IO|WF_DEBUG_CMD), "cannot request "
+ "0x%x [%s].\n",
+ cmd, wfcmd->action);
return 1;
}
if (wfcmd->write_cnt > 0) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: writing %d bytes "
- "for 0x%x\n",
- wfcmd->write_cnt, cmd);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_DATA, "writing %d bytes "
+ "for 0x%x\n",
+ wfcmd->write_cnt, cmd);
for (i = 0; i < wfcmd->write_cnt; i++) {
- if (!wavefront_write (hw, wbuf[i])) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG
- "WaveFront: bad write for byte %d of 0x%x [%s].\n",
- i, cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ if (wavefront_write (wbuf[i])) {
+ DPRINT (WF_DEBUG_IO, "bad write for byte "
+ "%d of 0x%x [%s].\n",
+ i, cmd, wfcmd->action);
return 1;
}
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG
- "WaveFront: write[%d] = 0x%x\n",
- i, wbuf[i]);
-#endif WF_DEBUG
- }
+
+ DPRINT (WF_DEBUG_DATA, "write[%d] = 0x%x\n",
+ i, wbuf[i]);
}
}
if (wfcmd->read_cnt > 0) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: reading %d ints "
- "for 0x%x\n",
- wfcmd->read_cnt, cmd);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_DATA, "reading %d ints "
+ "for 0x%x\n",
+ wfcmd->read_cnt, cmd);
for (i = 0; i < wfcmd->read_cnt; i++) {
- if ((c = wavefront_read(hw)) == -1) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG
- "WaveFront: bad read for byte %d of 0x%x [%s].\n",
- i, cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ if ((c = wavefront_read()) == -1) {
+ DPRINT (WF_DEBUG_IO, "bad read for byte "
+ "%d of 0x%x [%s].\n",
+ i, cmd, wfcmd->action);
return 1;
}
/* Now handle errors. Lots of special cases here */
if (c == 0xff) {
- if ((c = wavefront_read (hw)) == -1) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG
- "WaveFront: bad read for error byte at "
- "read byte %d of 0x%x [%s].\n",
- i, cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ if ((c = wavefront_read ()) == -1) {
+ DPRINT (WF_DEBUG_IO, "bad read for "
+ "error byte at "
+ "read byte %d "
+ "of 0x%x [%s].\n",
+ i, cmd,
+ wfcmd->action);
return 1;
}
@@ -553,60 +612,44 @@ wavefront_cmd (wf_config *hw, int cmd,
} else {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG
- "WaveFront: error %d (%s) during "
- "read for byte "
- "%d of 0x%x [%s].\n",
- c,
- wavefront_errorstr (c),
- i, cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_IO, "error %d (%s) "
+ "during "
+ "read for byte "
+ "%d of 0x%x "
+ "[%s].\n",
+ c,
+ wavefront_errorstr (c),
+ i, cmd,
+ wfcmd->action);
return 1;
}
- } else {
+
+ } else {
rbuf[i] = c;
}
-
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG
- "WaveFront: read[%d] = 0x%x\n",
- i, rbuf[i]);
- }
-#endif WF_DEBUG
+
+ DPRINT (WF_DEBUG_DATA, "read[%d] = 0x%x\n",i, rbuf[i]);
}
}
-
+
if ((wfcmd->read_cnt == 0 && wfcmd->write_cnt == 0) || wfcmd->need_ack) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_CMD) {
- printk (KERN_DEBUG "WaveFront: reading ACK for 0x%x\n",
- cmd);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_CMD, "reading ACK for 0x%x\n", cmd);
/* Some commands need an ACK, but return zero instead
of the standard value.
*/
- if ((ack = wavefront_read(hw)) == 0) {
+ if ((ack = wavefront_read()) == 0) {
ack = WF_ACK;
}
if (ack != WF_ACK) {
if (ack == -1) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG
- "WaveFront: cannot read ack for 0x%x [%s].\n",
- cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_IO, "cannot read ack for "
+ "0x%x [%s].\n",
+ cmd, wfcmd->action);
return 1;
} else {
@@ -614,47 +657,32 @@ wavefront_cmd (wf_config *hw, int cmd,
if (ack == 0xff) { /* explicit error */
- if ((err = wavefront_read (hw)) == -1) {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG
- "WaveFront: cannot read err for 0x%x [%s].\n",
- cmd, wfcmd->action);
- }
-#endif WF_DEBUG
+ if ((err = wavefront_read ()) == -1) {
+ DPRINT (WF_DEBUG_DATA,
+ "cannot read err "
+ "for 0x%x [%s].\n",
+ cmd, wfcmd->action);
}
}
-
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG
- "WaveFront: 0x%x [%s] "
- "failed (0x%x, 0x%x, %s)\n",
- cmd, wfcmd->action, ack, err,
- wavefront_errorstr (err));
- }
-#endif WF_DEBUG
+
+ DPRINT (WF_DEBUG_IO, "0x%x [%s] "
+ "failed (0x%x, 0x%x, %s)\n",
+ cmd, wfcmd->action, ack, err,
+ wavefront_errorstr (err));
+
return -err;
- }
- }
-
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: ack received "
- "for 0x%x [%s]\n",
- cmd, wfcmd->action);
+ }
}
-#endif WF_DEBUG
+
+ DPRINT (WF_DEBUG_DATA, "ack received "
+ "for 0x%x [%s]\n",
+ cmd, wfcmd->action);
} else {
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_CMD) {
- printk (KERN_DEBUG
- "Wavefront: 0x%x [%s] does not need "
- "ACK (%d,%d,%d)\n",
- cmd, wfcmd->action, wfcmd->read_cnt,
- wfcmd->write_cnt, wfcmd->need_ack);
-#endif WF_DEBUG
- }
+
+ DPRINT (WF_DEBUG_CMD, "0x%x [%s] does not need "
+ "ACK (%d,%d,%d)\n",
+ cmd, wfcmd->action, wfcmd->read_cnt,
+ wfcmd->write_cnt, wfcmd->need_ack);
}
return 0;
@@ -749,7 +777,7 @@ WaveFront: sample, patch and program management.
***********************************************************************/
static int
-wavefront_delete_sample (wf_config *hw, int sample_num)
+wavefront_delete_sample (int sample_num)
{
unsigned char wbuf[2];
@@ -758,15 +786,15 @@ wavefront_delete_sample (wf_config *hw, int sample_num)
wbuf[0] = sample_num & 0x7f;
wbuf[1] = sample_num >> 7;
- if ((x = wavefront_cmd (hw, WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
- hw->sample_status[sample_num] = WF_ST_EMPTY;
+ if ((x = wavefront_cmd (WFC_DELETE_SAMPLE, 0, wbuf)) == 0) {
+ dev.sample_status[sample_num] = WF_ST_EMPTY;
}
return x;
}
static int
-wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
+wavefront_get_sample_status (int assume_rom)
{
int i;
@@ -775,29 +803,30 @@ wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
/* check sample status */
- if (wavefront_cmd (hw, WFC_GET_NSAMPLES, rbuf, wbuf)) {
- printk ("WaveFront: cannot request sample count.\n");
+ if (wavefront_cmd (WFC_GET_NSAMPLES, rbuf, wbuf)) {
+ printk (KERN_WARNING LOGNAME "cannot request sample count.\n");
+ return -1;
}
- sc_real = sc_alias = sc_multi = hw->samples_used = 0;
+ sc_real = sc_alias = sc_multi = dev.samples_used = 0;
for (i = 0; i < WF_MAX_SAMPLE; i++) {
wbuf[0] = i & 0x7f;
wbuf[1] = i >> 7;
- if (wavefront_cmd (hw, WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
- printk (KERN_WARNING
- "WaveFront: cannot identify sample "
+ if (wavefront_cmd (WFC_IDENTIFY_SAMPLE_TYPE, rbuf, wbuf)) {
+ printk (KERN_WARNING LOGNAME
+ "cannot identify sample "
"type of slot %d\n", i);
- hw->sample_status[i] = WF_ST_EMPTY;
+ dev.sample_status[i] = WF_ST_EMPTY;
continue;
}
- hw->sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
+ dev.sample_status[i] = (WF_SLOT_FILLED|rbuf[0]);
if (assume_rom) {
- hw->sample_status[i] |= WF_SLOT_ROM;
+ dev.sample_status[i] |= WF_SLOT_ROM;
}
switch (rbuf[0] & WF_ST_MASK) {
@@ -814,21 +843,20 @@ wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
break;
default:
- printk (KERN_WARNING
- "WaveFront: unknown sample type for "
+ printk (KERN_WARNING LOGNAME "unknown sample type for "
"slot %d (0x%x)\n",
i, rbuf[0]);
}
if (rbuf[0] != WF_ST_EMPTY) {
- hw->samples_used++;
+ dev.samples_used++;
}
}
- printk (KERN_INFO
- "WaveFront: %d samples used (%d real, %d aliases, %d multi), "
- "%d empty\n", hw->samples_used, sc_real, sc_alias, sc_multi,
- WF_MAX_SAMPLE - hw->samples_used);
+ printk (KERN_INFO LOGNAME
+ "%d samples used (%d real, %d aliases, %d multi), "
+ "%d empty\n", dev.samples_used, sc_real, sc_alias, sc_multi,
+ WF_MAX_SAMPLE - dev.samples_used);
return (0);
@@ -836,7 +864,8 @@ wavefront_get_sample_status (struct wf_config *hw, int assume_rom)
}
static int
-wavefront_get_patch_status (struct wf_config *hw)
+wavefront_get_patch_status (void)
+
{
unsigned char patchbuf[WF_PATCH_BYTES];
unsigned char patchnum[2];
@@ -847,21 +876,21 @@ wavefront_get_patch_status (struct wf_config *hw)
patchnum[0] = i & 0x7f;
patchnum[1] = i >> 7;
- if ((x = wavefront_cmd (hw, WFC_UPLOAD_PATCH, patchbuf,
+ if ((x = wavefront_cmd (WFC_UPLOAD_PATCH, patchbuf,
patchnum)) == 0) {
- hw->patch_status[i] |= WF_SLOT_FILLED;
+ dev.patch_status[i] |= WF_SLOT_FILLED;
p = (wavefront_patch *) patchbuf;
- hw->sample_status
+ dev.sample_status
[p->sample_number|(p->sample_msb<<7)] |=
WF_SLOT_USED;
} else if (x == 3) { /* Bad patch number */
- hw->patch_status[i] = 0;
+ dev.patch_status[i] = 0;
} else {
- printk (KERN_ERR "WaveFront: upload patch "
+ printk (KERN_ERR LOGNAME "upload patch "
"error 0x%x\n", x);
- hw->patch_status[i] = 0;
+ dev.patch_status[i] = 0;
return 1;
}
}
@@ -869,22 +898,23 @@ wavefront_get_patch_status (struct wf_config *hw)
/* program status has already filled in slot_used bits */
for (i = 0, cnt = 0, cnt2 = 0; i < WF_MAX_PATCH; i++) {
- if (hw->patch_status[i] & WF_SLOT_FILLED) {
+ if (dev.patch_status[i] & WF_SLOT_FILLED) {
cnt++;
}
- if (hw->patch_status[i] & WF_SLOT_USED) {
+ if (dev.patch_status[i] & WF_SLOT_USED) {
cnt2++;
}
}
- printk (KERN_INFO
- "WaveFront: %d patch slots filled, %d in use\n", cnt, cnt2);
+ printk (KERN_INFO LOGNAME
+ "%d patch slots filled, %d in use\n", cnt, cnt2);
return (0);
}
static int
-wavefront_get_program_status (struct wf_config *hw)
+wavefront_get_program_status (void)
+
{
unsigned char progbuf[WF_PROGRAM_BYTES];
wavefront_program prog;
@@ -894,64 +924,59 @@ wavefront_get_program_status (struct wf_config *hw)
for (i = 0; i < WF_MAX_PROGRAM; i++) {
prognum = i;
- if ((x = wavefront_cmd (hw, WFC_UPLOAD_PROGRAM, progbuf,
+ if ((x = wavefront_cmd (WFC_UPLOAD_PROGRAM, progbuf,
&prognum)) == 0) {
- hw->prog_status[i] |= WF_SLOT_USED;
+ dev.prog_status[i] |= WF_SLOT_USED;
demunge_buf (progbuf, (unsigned char *) &prog,
WF_PROGRAM_BYTES);
for (l = 0; l < WF_NUM_LAYERS; l++) {
if (prog.layer[l].mute) {
- hw->patch_status
+ dev.patch_status
[prog.layer[l].patch_number] |=
WF_SLOT_USED;
}
}
} else if (x == 1) { /* Bad program number */
- hw->prog_status[i] = 0;
+ dev.prog_status[i] = 0;
} else {
- printk (KERN_ERR "WaveFront: upload program "
+ printk (KERN_ERR LOGNAME "upload program "
"error 0x%x\n", x);
- hw->prog_status[i] = 0;
+ dev.prog_status[i] = 0;
}
}
for (i = 0, cnt = 0; i < WF_MAX_PROGRAM; i++) {
- if (hw->prog_status[i]) {
+ if (dev.prog_status[i]) {
cnt++;
}
}
- printk (KERN_INFO "WaveFront: %d programs slots in use\n", cnt);
+ printk (KERN_INFO LOGNAME "%d programs slots in use\n", cnt);
return (0);
}
static int
-wavefront_send_patch (wf_config *hw,
- wavefront_patch_info *header)
+wavefront_send_patch (wavefront_patch_info *header)
{
unsigned char buf[WF_PATCH_BYTES+2];
unsigned char *bptr;
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG "WaveFront: downloading patch %d\n",
- header->number);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n",
+ header->number);
- hw->patch_status[header->number] |= WF_SLOT_FILLED;
+ dev.patch_status[header->number] |= WF_SLOT_FILLED;
bptr = buf;
bptr = munge_int32 (header->number, buf, 2);
munge_buf ((unsigned char *)&header->hdr.p, bptr, WF_PATCH_BYTES);
- if (wavefront_cmd (hw, WFC_DOWNLOAD_PATCH, 0, buf)) {
- printk (KERN_ERR "WaveFront: download patch failed\n");
+ if (wavefront_cmd (WFC_DOWNLOAD_PATCH, 0, buf)) {
+ printk (KERN_ERR LOGNAME "download patch failed\n");
return -(EIO);
}
@@ -959,21 +984,16 @@ wavefront_send_patch (wf_config *hw,
}
static int
-wavefront_send_program (wf_config *hw,
- wavefront_patch_info *header)
+wavefront_send_program (wavefront_patch_info *header)
{
unsigned char buf[WF_PROGRAM_BYTES+1];
int i;
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG
- "WaveFront: downloading program %d\n", header->number);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n",
+ header->number);
- hw->prog_status[header->number] = WF_SLOT_USED;
+ dev.prog_status[header->number] = WF_SLOT_USED;
/* XXX need to zero existing SLOT_USED bit for program_status[i]
where `i' is the program that's being (potentially) overwritten.
@@ -981,7 +1001,7 @@ wavefront_send_program (wf_config *hw,
for (i = 0; i < WF_NUM_LAYERS; i++) {
if (header->hdr.pr.layer[i].mute) {
- hw->patch_status[header->hdr.pr.layer[i].patch_number] |=
+ dev.patch_status[header->hdr.pr.layer[i].patch_number] |=
WF_SLOT_USED;
/* XXX need to mark SLOT_USED for sample used by
@@ -993,8 +1013,8 @@ wavefront_send_program (wf_config *hw,
buf[0] = header->number;
munge_buf ((unsigned char *)&header->hdr.pr, &buf[1], WF_PROGRAM_BYTES);
- if (wavefront_cmd (hw, WFC_DOWNLOAD_PROGRAM, 0, buf)) {
- printk (KERN_WARNING "WaveFront: download patch failed\n");
+ if (wavefront_cmd (WFC_DOWNLOAD_PROGRAM, 0, buf)) {
+ printk (KERN_WARNING LOGNAME "download patch failed\n");
return -(EIO);
}
@@ -1002,13 +1022,13 @@ wavefront_send_program (wf_config *hw,
}
static int
-wavefront_freemem (wf_config *hw)
+wavefront_freemem (void)
{
char rbuf[8];
- if (wavefront_cmd (hw, WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
- printk (KERN_WARNING "WaveFront: can't get memory stats.\n");
+ if (wavefront_cmd (WFC_REPORT_FREE_MEMORY, rbuf, 0)) {
+ printk (KERN_WARNING LOGNAME "can't get memory stats.\n");
return -1;
} else {
return demunge_int32 (rbuf, 4);
@@ -1016,8 +1036,7 @@ wavefront_freemem (wf_config *hw)
}
static int
-wavefront_send_sample (wf_config *hw,
- wavefront_patch_info *header,
+wavefront_send_sample (wavefront_patch_info *header,
UINT16 *dataptr,
int data_is_unsigned)
@@ -1045,15 +1064,22 @@ wavefront_send_sample (wf_config *hw,
int skip = 0;
int initial_skip = 0;
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG "WaveFront: sample %sdownload for slot %d, "
- "type %d, %d bytes from 0x%x\n",
- header->size ? "" : "header ",
- header->number, header->subkey, header->size,
- (int) header->dataptr);
+ DPRINT (WF_DEBUG_LOAD_PATCH, "sample %sdownload for slot %d, "
+ "type %d, %d bytes from 0x%x\n",
+ header->size ? "" : "header ",
+ header->number, header->subkey,
+ header->size,
+ (int) header->dataptr);
+
+ if (header->number == WAVEFRONT_FIND_FREE_SAMPLE_SLOT) {
+ int x;
+
+ if ((x = wavefront_find_free_sample ()) < 0) {
+ return -ENOMEM;
+ }
+ printk (KERN_DEBUG LOGNAME "unspecified sample => %d\n", x);
+ header->number = x;
}
-#endif WF_DEBUG
if (header->size) {
@@ -1080,24 +1106,24 @@ wavefront_send_sample (wf_config *hw,
a copy of the patch/program/sample header data.
*/
- if (hw->rom_samples_rdonly) {
- if (hw->sample_status[header->number] & WF_SLOT_ROM) {
- printk (KERN_ERR "WaveFront: sample slot %d "
+ if (dev.rom_samples_rdonly) {
+ if (dev.sample_status[header->number] & WF_SLOT_ROM) {
+ printk (KERN_ERR LOGNAME "sample slot %d "
"write protected\n",
header->number);
return -EACCES;
}
}
- wavefront_delete_sample (hw, header->number);
+ wavefront_delete_sample (header->number);
}
if (header->size) {
- hw->freemem = wavefront_freemem (hw);
+ dev.freemem = wavefront_freemem ();
- if (hw->freemem < header->size) {
- printk (KERN_ERR
- "WaveFront: insufficient memory to "
+ if (dev.freemem < header->size) {
+ printk (KERN_ERR LOGNAME
+ "insufficient memory to "
"load %d byte sample.\n",
header->size);
return -ENOMEM;
@@ -1107,16 +1133,10 @@ wavefront_send_sample (wf_config *hw,
skip = WF_GET_CHANNEL(&header->hdr.s);
- if (skip > 0) {
- switch (header->hdr.s.SampleResolution) {
- case LINEAR_16BIT:
- break;
- default:
- printk (KERN_ERR
- "WaveFront: channel selection only possible "
- "on 16-bit samples");
- return -(EINVAL);
- }
+ if (skip > 0 && header->hdr.s.SampleResolution != LINEAR_16BIT) {
+ printk (KERN_ERR LOGNAME "channel selection only "
+ "possible on 16-bit samples");
+ return -(EINVAL);
}
switch (skip) {
@@ -1150,13 +1170,10 @@ wavefront_send_sample (wf_config *hw,
break;
}
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG "WaveFront: channel selection: %d => "
- "initial skip = %d, skip = %d\n",
- WF_GET_CHANNEL (&header->hdr.s), initial_skip, skip);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "channel selection: %d => "
+ "initial skip = %d, skip = %d\n",
+ WF_GET_CHANNEL (&header->hdr.s),
+ initial_skip, skip);
/* Be safe, and zero the "Unused" bits ... */
@@ -1210,10 +1227,10 @@ wavefront_send_sample (wf_config *hw,
shptr = munge_int32 (*(&header->hdr.s.FrequencyBias+1),
shptr, 2);
- if (wavefront_cmd (hw, header->size ?
+ if (wavefront_cmd (header->size ?
WFC_DOWNLOAD_SAMPLE : WFC_DOWNLOAD_SAMPLE_HEADER,
0, sample_hdr)) {
- printk (KERN_WARNING "WaveFront: sample %sdownload refused.\n",
+ printk (KERN_WARNING LOGNAME "sample %sdownload refused.\n",
header->size ? "" : "header ");
return -(EIO);
}
@@ -1238,8 +1255,8 @@ wavefront_send_sample (wf_config *hw,
blocksize = ((length-written+7)&~0x7);
}
- if (wavefront_cmd (hw, WFC_DOWNLOAD_BLOCK, 0, 0)) {
- printk (KERN_WARNING "WaveFront: download block "
+ if (wavefront_cmd (WFC_DOWNLOAD_BLOCK, 0, 0)) {
+ printk (KERN_WARNING LOGNAME "download block "
"request refused.\n");
return -(EIO);
}
@@ -1248,7 +1265,7 @@ wavefront_send_sample (wf_config *hw,
if (dataptr < data_end) {
- get_user (sample_short, dataptr);
+ __get_user (sample_short, dataptr);
dataptr += skip;
if (data_is_unsigned) { /* GUS ? */
@@ -1287,21 +1304,23 @@ wavefront_send_sample (wf_config *hw,
}
if (i < blocksize - 1) {
- outw (sample_short, hw->block_port);
+ outw (sample_short, dev.block_port);
} else {
- outw (sample_short, hw->last_block_port);
+ outw (sample_short, dev.last_block_port);
}
}
- /* Get "DMA page acknowledge" */
+ /* Get "DMA page acknowledge", even though its really
+ nothing to do with DMA at all.
+ */
- if ((dma_ack = wavefront_read (hw)) != WF_DMA_ACK) {
+ if ((dma_ack = wavefront_read ()) != WF_DMA_ACK) {
if (dma_ack == -1) {
- printk (KERN_ERR "WaveFront: upload sample "
+ printk (KERN_ERR LOGNAME "upload sample "
"DMA ack timeout\n");
return -(EIO);
} else {
- printk (KERN_ERR "WaveFront: upload sample "
+ printk (KERN_ERR LOGNAME "upload sample "
"DMA ack error 0x%x\n",
dma_ack);
return -(EIO);
@@ -1309,7 +1328,7 @@ wavefront_send_sample (wf_config *hw,
}
}
- hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
+ dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_SAMPLE);
/* Note, label is here because sending the sample header shouldn't
alter the sample_status info at all.
@@ -1320,20 +1339,15 @@ wavefront_send_sample (wf_config *hw,
}
static int
-wavefront_send_alias (struct wf_config *hw,
- wavefront_patch_info *header)
+wavefront_send_alias (wavefront_patch_info *header)
{
unsigned char alias_hdr[WF_ALIAS_BYTES];
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG "WaveFront: download alias, %d is "
- "alias for %d\n",
- header->number,
- header->hdr.a.OriginalSample);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "download alias, %d is "
+ "alias for %d\n",
+ header->number,
+ header->hdr.a.OriginalSample);
munge_int32 (header->number, &alias_hdr[0], 2);
munge_int32 (header->hdr.a.OriginalSample, &alias_hdr[2], 2);
@@ -1348,19 +1362,18 @@ wavefront_send_alias (struct wf_config *hw,
munge_int32 (header->hdr.a.FrequencyBias, &alias_hdr[20], 3);
munge_int32 (*(&header->hdr.a.FrequencyBias+1), &alias_hdr[23], 2);
- if (wavefront_cmd (hw, WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
- printk (KERN_ERR "WaveFront: download alias failed.\n");
+ if (wavefront_cmd (WFC_DOWNLOAD_SAMPLE_ALIAS, 0, alias_hdr)) {
+ printk (KERN_ERR LOGNAME "download alias failed.\n");
return -(EIO);
}
- hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
+ dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_ALIAS);
return (0);
}
static int
-wavefront_send_multisample (struct wf_config *hw,
- wavefront_patch_info *header)
+wavefront_send_multisample (wavefront_patch_info *header)
{
int i;
int num_samples;
@@ -1376,23 +1389,16 @@ wavefront_send_multisample (struct wf_config *hw,
num_samples = (1<<(header->hdr.ms.NumberOfSamples&7));
msample_hdr[2] = (unsigned char) header->hdr.ms.NumberOfSamples;
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG "WaveFront: multi %d with %d=%d samples\n",
- header->number, header->hdr.ms.NumberOfSamples, num_samples);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "multi %d with %d=%d samples\n",
+ header->number,
+ header->hdr.ms.NumberOfSamples,
+ num_samples);
for (i = 0; i < num_samples; i++) {
-#ifdef WF_DEBUG
- if ((hw->debug & (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) ==
- (WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA)) {
- printk (KERN_DEBUG "WaveFront: sample[%d] = %d\n",
- i, header->hdr.ms.SampleNumber[i]);
- }
-#endif WF_DEBUG
+ DPRINT(WF_DEBUG_LOAD_PATCH|WF_DEBUG_DATA, "sample[%d] = %d\n",
+ i, header->hdr.ms.SampleNumber[i]);
munge_int32 (header->hdr.ms.SampleNumber[i],
- &msample_hdr[3+(i*2)], 2);
+ &msample_hdr[3+(i*2)], 2);
}
/* Need a hack here to pass in the number of bytes
@@ -1400,21 +1406,20 @@ wavefront_send_multisample (struct wf_config *hw,
one day, I'll fix it.
*/
- if (wavefront_cmd (hw, WFC_DOWNLOAD_MULTISAMPLE,
+ if (wavefront_cmd (WFC_DOWNLOAD_MULTISAMPLE,
(unsigned char *) ((num_samples*2)+3),
msample_hdr)) {
- printk (KERN_ERR "WaveFront: download of multisample failed.\n");
+ printk (KERN_ERR LOGNAME "download of multisample failed.\n");
return -(EIO);
}
- hw->sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
+ dev.sample_status[header->number] = (WF_SLOT_FILLED|WF_ST_MULTISAMPLE);
return (0);
}
static int
-wavefront_fetch_multisample (struct wf_config *hw,
- wavefront_patch_info *header)
+wavefront_fetch_multisample (wavefront_patch_info *header)
{
int i;
unsigned char log_ns[1];
@@ -1423,17 +1428,13 @@ wavefront_fetch_multisample (struct wf_config *hw,
munge_int32 (header->number, number, 2);
- if (wavefront_cmd (hw, WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
- printk (KERN_ERR "WaveFront: upload multisample failed.\n");
+ if (wavefront_cmd (WFC_UPLOAD_MULTISAMPLE, log_ns, number)) {
+ printk (KERN_ERR LOGNAME "upload multisample failed.\n");
return -(EIO);
}
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: msample %d has %d samples\n",
- header->number, log_ns[0]);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_DATA, "msample %d has %d samples\n",
+ header->number, log_ns[0]);
header->hdr.ms.NumberOfSamples = log_ns[0];
@@ -1444,14 +1445,14 @@ wavefront_fetch_multisample (struct wf_config *hw,
for (i = 0; i < num_samples; i++) {
char d[2];
- if ((d[0] = wavefront_read (hw)) == -1) {
- printk (KERN_ERR "WaveFront: upload multisample failed "
+ if ((d[0] = wavefront_read ()) == -1) {
+ printk (KERN_ERR LOGNAME "upload multisample failed "
"during sample loop.\n");
return -(EIO);
}
- if ((d[1] = wavefront_read (hw)) == -1) {
- printk (KERN_ERR "WaveFront: upload multisample failed "
+ if ((d[1] = wavefront_read ()) == -1) {
+ printk (KERN_ERR LOGNAME "upload multisample failed "
"during sample loop.\n");
return -(EIO);
}
@@ -1459,13 +1460,8 @@ wavefront_fetch_multisample (struct wf_config *hw,
header->hdr.ms.SampleNumber[i] =
demunge_int32 ((unsigned char *) d, 2);
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_DATA) {
- printk (KERN_DEBUG "WaveFront: msample "
- "sample[%d] = %d\n",
- i, header->hdr.ms.SampleNumber[i]);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_DATA, "msample sample[%d] = %d\n",
+ i, header->hdr.ms.SampleNumber[i]);
}
return (0);
@@ -1473,21 +1469,16 @@ wavefront_fetch_multisample (struct wf_config *hw,
static int
-wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
+wavefront_send_drum (wavefront_patch_info *header)
{
unsigned char drumbuf[WF_DRUM_BYTES];
wavefront_drum *drum = &header->hdr.d;
int i;
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG
- "WaveFront: downloading edrum for MIDI "
- "note %d, patch = %d\n",
- header->number, drum->PatchNumber);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "downloading edrum for MIDI "
+ "note %d, patch = %d\n",
+ header->number, drum->PatchNumber);
drumbuf[0] = header->number & 0x7f;
@@ -1495,8 +1486,8 @@ wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
munge_int32 (((unsigned char *)drum)[i], &drumbuf[1+(i*2)], 2);
}
- if (wavefront_cmd (hw, WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
- printk (KERN_ERR "WaveFront: download drum failed.\n");
+ if (wavefront_cmd (WFC_DOWNLOAD_EDRUM_PROGRAM, 0, drumbuf)) {
+ printk (KERN_ERR LOGNAME "download drum failed.\n");
return -(EIO);
}
@@ -1504,32 +1495,32 @@ wavefront_send_drum (struct wf_config *hw, wavefront_patch_info *header)
}
static int
-wavefront_find_free_sample (struct wf_config *hw)
+wavefront_find_free_sample (void)
{
int i;
for (i = 0; i < WF_MAX_SAMPLE; i++) {
- if (!(hw->sample_status[i] & WF_SLOT_FILLED)) {
+ if (!(dev.sample_status[i] & WF_SLOT_FILLED)) {
return i;
}
}
- printk (KERN_WARNING "WaveFront: no free sample slots!\n");
+ printk (KERN_WARNING LOGNAME "no free sample slots!\n");
return -1;
}
static int
-wavefront_find_free_patch (struct wf_config *hw)
+wavefront_find_free_patch (void)
{
int i;
for (i = 0; i < WF_MAX_PATCH; i++) {
- if (!(hw->patch_status[i] & WF_SLOT_FILLED)) {
+ if (!(dev.patch_status[i] & WF_SLOT_FILLED)) {
return i;
}
}
- printk (KERN_WARNING "WaveFront: no free patch slots!\n");
+ printk (KERN_WARNING LOGNAME "no free patch slots!\n");
return -1;
}
@@ -1562,8 +1553,7 @@ log2_2048(int n)
}
static int
-wavefront_load_gus_patch (struct wf_config *hw,
- int dev, int format, const char *addr,
+wavefront_load_gus_patch (int devno, int format, const char *addr,
int offs, int count, int pmgr_flag)
{
struct patch_info guspatch;
@@ -1581,14 +1571,14 @@ wavefront_load_gus_patch (struct wf_config *hw,
copy_from_user (&((char *) &guspatch)[offs],
&(addr)[offs], sizeof_patch - offs);
- if ((i = wavefront_find_free_patch (hw)) == -1) {
+ if ((i = wavefront_find_free_patch ()) == -1) {
return -EBUSY;
}
pat.number = i;
pat.subkey = WF_ST_PATCH;
patp = &pat.hdr.p;
- if ((i = wavefront_find_free_sample (hw)) == -1) {
+ if ((i = wavefront_find_free_sample ()) == -1) {
return -EBUSY;
}
samp.number = i;
@@ -1644,7 +1634,7 @@ wavefront_load_gus_patch (struct wf_config *hw,
progp->layer[0].mix_level=127 /* guspatch.volume */;
progp->layer[0].split_type=0;
progp->layer[0].split_point=0;
- progp->layer[0].updown=0;
+ progp->layer[0].play_below=0;
for (i = 1; i < 4; i++) {
progp->layer[i].mute=0;
@@ -1685,11 +1675,11 @@ wavefront_load_gus_patch (struct wf_config *hw,
/* Now ship it down */
- wavefront_send_sample (hw, &samp,
+ wavefront_send_sample (&samp,
(unsigned short *) &(addr)[sizeof_patch],
(guspatch.mode & WAVE_UNSIGNED) ? 1:0);
- wavefront_send_patch (hw, &pat);
- wavefront_send_program (hw, &prog);
+ wavefront_send_patch (&pat);
+ wavefront_send_program (&prog);
/* Now pan as best we can ... use the slave/internal MIDI device
number if it exists (since it talks to the WaveFront), or the
@@ -1697,8 +1687,8 @@ wavefront_load_gus_patch (struct wf_config *hw,
*/
#ifdef CONFIG_MIDI
- if (hw->mididev > 0) {
- midi_synth_controller (hw->mididev, guspatch.instr_no, 10,
+ if (dev.mididev > 0) {
+ midi_synth_controller (dev.mididev, guspatch.instr_no, 10,
((guspatch.panning << 4) > 127) ?
127 : (guspatch.panning << 4));
}
@@ -1707,60 +1697,26 @@ wavefront_load_gus_patch (struct wf_config *hw,
return(0);
}
-int
-wavefront_load_patch (int dev, int format, const char *addr,
- int offs, int count, int pmgr_flag)
-{
-
- struct wf_config *hw = &wavefront_configuration;
- wavefront_patch_info header;
-
- if (format == SYSEX_PATCH) { /* Handled by midi_synth.c */
- if (midi_load_patch == NULL) {
- printk (KERN_ERR
- "WaveFront: SYSEX not loadable: "
- "no midi patch loader!\n");
- return -(EINVAL);
- }
- return midi_load_patch (dev, format, addr,
- offs, count, pmgr_flag);
-
- } else if (format == GUS_PATCH) {
- return wavefront_load_gus_patch (hw, dev, format,
- addr, offs, count, pmgr_flag);
+static int
+wavefront_load_patch (const char *addr)
- } else if (format != WAVEFRONT_PATCH) {
- printk (KERN_ERR "WaveFront: unknown patch format %d\n", format);
- return -(EINVAL);
- }
- if (count < sizeof (wavefront_patch_info)) {
- printk (KERN_ERR "WaveFront: sample header too short\n");
+{
+ wavefront_patch_info header;
+
+ if (copy_from_user (&header, addr, sizeof(wavefront_patch_info) -
+ sizeof(wavefront_any))) {
+ printk (KERN_WARNING LOGNAME "bad address for load patch.\n");
return -(EINVAL);
}
- /* copied in so far: `offs' bytes from `addr'. We shouldn't copy
- them in again, and they correspond to header->key and header->devno.
- So now, copy the rest of the wavefront_patch_info struct, except
- for the 'hdr' field, since this is handled via indirection
- through the 'hdrptr' field.
- */
-
- copy_from_user (&((char *) &header)[offs], &(addr)[offs],
- sizeof(wavefront_patch_info) -
- sizeof(wavefront_any) - offs);
-
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_LOAD_PATCH) {
- printk (KERN_DEBUG "WaveFront: download "
- "Sample type: %d "
- "Sample number: %d "
- "Sample size: %d\n",
- header.subkey,
- header.number,
- header.size);
- }
-#endif WF_DEBUG
+ DPRINT (WF_DEBUG_LOAD_PATCH, "download "
+ "Sample type: %d "
+ "Sample number: %d "
+ "Sample size: %d\n",
+ header.subkey,
+ header.number,
+ header.size);
switch (header.subkey) {
case WF_ST_SAMPLE: /* sample or sample_header, based on patch->size */
@@ -1769,7 +1725,7 @@ wavefront_load_patch (int dev, int format, const char *addr,
(unsigned char *) header.hdrptr,
sizeof (wavefront_sample));
- return wavefront_send_sample (hw, &header, header.dataptr, 0);
+ return wavefront_send_sample (&header, header.dataptr, 0);
case WF_ST_MULTISAMPLE:
@@ -1777,7 +1733,7 @@ wavefront_load_patch (int dev, int format, const char *addr,
(unsigned char *) header.hdrptr,
sizeof (wavefront_multisample));
- return wavefront_send_multisample (hw, &header);
+ return wavefront_send_multisample (&header);
case WF_ST_ALIAS:
@@ -1786,31 +1742,31 @@ wavefront_load_patch (int dev, int format, const char *addr,
(unsigned char *) header.hdrptr,
sizeof (wavefront_alias));
- return wavefront_send_alias (hw, &header);
+ return wavefront_send_alias (&header);
case WF_ST_DRUM:
copy_from_user ((unsigned char *) &header.hdr.d,
(unsigned char *) header.hdrptr,
sizeof (wavefront_drum));
- return wavefront_send_drum (hw, &header);
+ return wavefront_send_drum (&header);
case WF_ST_PATCH:
copy_from_user ((unsigned char *) &header.hdr.p,
(unsigned char *) header.hdrptr,
sizeof (wavefront_patch));
- return wavefront_send_patch (hw, &header);
+ return wavefront_send_patch (&header);
case WF_ST_PROGRAM:
copy_from_user ((unsigned char *) &header.hdr.pr,
(unsigned char *) header.hdrptr,
sizeof (wavefront_program));
- return wavefront_send_program (hw, &header);
+ return wavefront_send_program (&header);
default:
- printk (KERN_ERR "WaveFront: unknown patch type %d.\n",
+ printk (KERN_ERR LOGNAME "unknown patch type %d.\n",
header.subkey);
return -(EINVAL);
}
@@ -1855,155 +1811,248 @@ process_sample_hdr (UCHAR8 *buf)
}
static int
-wavefront_synth_control (int dev, int cmd, caddr_t arg)
+wavefront_synth_control (int cmd, wavefront_control *wc)
{
- struct wf_config *hw = &wavefront_configuration;
- wavefront_control wc;
unsigned char patchnumbuf[2];
int i;
- copy_from_user (&wc, arg, sizeof (wc));
+ DPRINT (WF_DEBUG_CMD, "synth control with "
+ "cmd 0x%x\n", wc->cmd);
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_CMD) {
- printk (KERN_DEBUG "WaveFront: synth control with "
- "cmd 0x%x\n", wc.cmd);
- }
-#endif WF_DEBUG
-
- /* special case handling of or for various commands */
+ /* Pre-handling of or for various commands */
- switch (wc.cmd) {
+ switch (wc->cmd) {
case WFC_DISABLE_INTERRUPTS:
- printk (KERN_INFO "WaveFront: interrupts disabled.\n");
- outb (0x80|0x20, hw->control_port);
- hw->interrupts_on = 0;
+ printk (KERN_INFO LOGNAME "interrupts disabled.\n");
+ outb (0x80|0x20, dev.control_port);
+ dev.interrupts_on = 0;
return 0;
case WFC_ENABLE_INTERRUPTS:
- printk (KERN_INFO "WaveFront: interrupts enabled.\n");
- outb (0x80|0x20|0x40, hw->control_port);
- hw->interrupts_on = 1;
+ printk (KERN_INFO LOGNAME "interrupts enabled.\n");
+ outb (0x80|0x40|0x20, dev.control_port);
+ dev.interrupts_on = 1;
return 0;
case WFC_INTERRUPT_STATUS:
- wc.rbuf[0] = hw->interrupts_on;
+ wc->rbuf[0] = dev.interrupts_on;
return 0;
case WFC_ROMSAMPLES_RDONLY:
- hw->rom_samples_rdonly = wc.wbuf[0];
- wc.status = 0;
+ dev.rom_samples_rdonly = wc->wbuf[0];
+ wc->status = 0;
return 0;
case WFC_IDENTIFY_SLOT_TYPE:
- i = wc.wbuf[0] | (wc.wbuf[1] << 7);
+ i = wc->wbuf[0] | (wc->wbuf[1] << 7);
if (i <0 || i >= WF_MAX_SAMPLE) {
- printk (KERN_WARNING "WaveFront: invalid slot ID %d\n",
+ printk (KERN_WARNING LOGNAME "invalid slot ID %d\n",
i);
- wc.status = EINVAL;
+ wc->status = EINVAL;
return 0;
}
- wc.rbuf[0] = hw->sample_status[i];
- wc.status = 0;
+ wc->rbuf[0] = dev.sample_status[i];
+ wc->status = 0;
return 0;
case WFC_DEBUG_DRIVER:
- hw->debug = wc.wbuf[0];
- printk (KERN_INFO "WaveFront: debug = 0x%x\n", hw->debug);
+ dev.debug = wc->wbuf[0];
+ printk (KERN_INFO LOGNAME "debug = 0x%x\n", dev.debug);
return 0;
case WFC_FX_IOCTL:
- wffx_ioctl (hw, (wavefront_fx_info *) &wc.wbuf[0]);
+ wffx_ioctl ((wavefront_fx_info *) &wc->wbuf[0]);
return 0;
case WFC_UPLOAD_PATCH:
- munge_int32 (*((UINT32 *) wc.wbuf), patchnumbuf, 2);
- memcpy (wc.wbuf, patchnumbuf, 2);
+ munge_int32 (*((UINT32 *) wc->wbuf), patchnumbuf, 2);
+ memcpy (wc->wbuf, patchnumbuf, 2);
break;
case WFC_UPLOAD_MULTISAMPLE:
+ /* multisamples have to be handled differently, and
+ cannot be dealt with properly by wavefront_cmd() alone.
+ */
+ wc->status = wavefront_fetch_multisample
+ ((wavefront_patch_info *) wc->rbuf);
+ return 0;
+
case WFC_UPLOAD_SAMPLE_ALIAS:
- printk (KERN_INFO "WaveFront: support for various uploads "
+ printk (KERN_INFO LOGNAME "support for sample alias upload "
"being considered.\n");
- wc.status = EINVAL;
+ wc->status = EINVAL;
return -EINVAL;
}
- wc.status = wavefront_cmd (hw, wc.cmd, wc.rbuf, wc.wbuf);
+ wc->status = wavefront_cmd (wc->cmd, wc->rbuf, wc->wbuf);
- /* Special case handling of certain commands.
+ /* Post-handling of certain commands.
In particular, if the command was an upload, demunge the data
so that the user-level doesn't have to think about it.
*/
- if (wc.status == 0) {
- switch (wc.cmd) {
+ if (wc->status == 0) {
+ switch (wc->cmd) {
/* intercept any freemem requests so that we know
we are always current with the user-level view
of things.
*/
case WFC_REPORT_FREE_MEMORY:
- hw->freemem = demunge_int32 (wc.rbuf, 4);
+ dev.freemem = demunge_int32 (wc->rbuf, 4);
break;
case WFC_UPLOAD_PATCH:
- demunge_buf (wc.rbuf, wc.rbuf, WF_PATCH_BYTES);
+ demunge_buf (wc->rbuf, wc->rbuf, WF_PATCH_BYTES);
break;
case WFC_UPLOAD_PROGRAM:
- demunge_buf (wc.rbuf, wc.rbuf, WF_PROGRAM_BYTES);
+ demunge_buf (wc->rbuf, wc->rbuf, WF_PROGRAM_BYTES);
break;
case WFC_UPLOAD_EDRUM_PROGRAM:
- demunge_buf (wc.rbuf, wc.rbuf, WF_DRUM_BYTES - 1);
+ demunge_buf (wc->rbuf, wc->rbuf, WF_DRUM_BYTES - 1);
break;
case WFC_UPLOAD_SAMPLE_HEADER:
- process_sample_hdr (wc.rbuf);
+ process_sample_hdr (wc->rbuf);
break;
- case WFC_UPLOAD_MULTISAMPLE:
case WFC_UPLOAD_SAMPLE_ALIAS:
- printk (KERN_INFO "WaveFront: support for "
- "various uploads "
+ printk (KERN_INFO LOGNAME "support for "
+ "sample aliases still "
"being considered.\n");
break;
case WFC_VMIDI_OFF:
- virtual_midi_disable (hw->mididev);
+ if (virtual_midi_disable () < 0) {
+ return -(EIO);
+ }
break;
case WFC_VMIDI_ON:
- virtual_midi_enable (hw->mididev, 0);
- break;
-
+ if (virtual_midi_enable () < 0) {
+ return -(EIO);
+ }
break;
}
}
- /* XXX It would be nice to avoid a complete copy of the whole
- struct sometimes. But I think its fast enough that this
- is a low priority fix.
- */
+ return 0;
+}
+
+
+/***********************************************************************/
+/* WaveFront: Linux file system interface (for access via raw synth) */
+/***********************************************************************/
+
+static loff_t
+wavefront_llseek(struct file *file, loff_t offset, int origin)
+{
+ return -ESPIPE;
+}
+
+static int
+wavefront_open (struct inode *inode, struct file *file)
+{
+ /* XXX fix me */
+ dev.opened = file->f_flags;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+wavefront_release(struct inode *inode, struct file *file)
+{
+ dev.opened = 0;
+ dev.debug = 0;
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int
+wavefront_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ wavefront_control wc;
+ int err;
+
+ switch (cmd) {
- copy_to_user (arg, &wc, sizeof (wc));
+ case WFCTL_WFCMD:
+ copy_from_user (&wc, (void *) arg, sizeof (wc));
+
+ if ((err = wavefront_synth_control (cmd, &wc)) == 0) {
+ copy_to_user ((void *) arg, &wc, sizeof (wc));
+ }
+
+ return err;
+
+ case WFCTL_LOAD_SPP:
+ return wavefront_load_patch ((const char *) arg);
+
+ default:
+ printk (KERN_WARNING LOGNAME "invalid ioctl %#x\n", cmd);
+ return -(EINVAL);
+
+ }
return 0;
}
+static /*const*/ struct file_operations wavefront_fops = {
+ &wavefront_llseek,
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ &wavefront_ioctl,
+ NULL, /* mmap */
+ &wavefront_open,
+ NULL, /* flush */
+ &wavefront_release,
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL, /* lock */
+};
+
-/***********************************************************************
-WaveFront: MIDI synth interface
-***********************************************************************/
+/***********************************************************************/
+/* WaveFront: OSS installation and support interface */
+/***********************************************************************/
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+
+static struct synth_info wavefront_info =
+{"Turtle Beach WaveFront", 0, SYNTH_TYPE_SAMPLE, SAMPLE_TYPE_WAVEFRONT,
+ 0, 32, 0, 0, SYNTH_CAP_INPUT};
+
+static int
+wavefront_oss_open (int devno, int mode)
+
+{
+ dev.opened = mode;
+ return 0;
+}
+
+static void
+wavefront_oss_close (int devno)
+{
+ dev.opened = 0;
+ dev.debug = 0;
+ return;
+}
static int
-wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
+wavefront_oss_ioctl (int devno, unsigned int cmd, caddr_t arg)
+
{
- wf_config *hw = &wavefront_configuration;
- unsigned char rbuf[4];
+ wavefront_control wc;
+ int err;
switch (cmd) {
case SNDCTL_SYNTH_INFO:
@@ -2013,183 +2062,156 @@ wavefront_ioctl (int dev, unsigned int cmd, caddr_t arg)
break;
case SNDCTL_SEQ_RESETSAMPLES:
- printk (KERN_WARNING
- "WaveFront: cannot reset sample status in kernel.\n");
+ printk (KERN_WARNING LOGNAME "driver cannot reset samples.\n");
return 0; /* don't force an error */
break;
case SNDCTL_SEQ_PERCMODE:
- /* XXX does this correspond to anything obvious ?*/
return 0; /* don't force an error */
break;
case SNDCTL_SYNTH_MEMAVL:
- if (wavefront_cmd (hw, WFC_REPORT_FREE_MEMORY, rbuf, 0) != 0) {
- printk (KERN_ERR
- "WaveFront: cannot get free memory size\n");
- return 0;
+ if ((dev.freemem = wavefront_freemem ()) < 0) {
+ printk (KERN_ERR LOGNAME "cannot get memory size\n");
+ return -EIO;
} else {
- hw->freemem = demunge_int32 (rbuf, 4);
- return hw->freemem;
+ return dev.freemem;
}
+ break;
case SNDCTL_SYNTH_CONTROL:
- return wavefront_synth_control (dev, cmd, arg);
+ copy_from_user (&wc, arg, sizeof (wc));
+
+ if ((err = wavefront_synth_control (cmd, &wc)) == 0) {
+ copy_to_user (arg, &wc, sizeof (wc));
+ }
+
+ return err;
default:
return -(EINVAL);
}
}
-static int
-wavefront_open (int dev, int mode)
-
+int
+wavefront_oss_load_patch (int devno, int format, const char *addr,
+ int offs, int count, int pmgr_flag)
{
- struct wf_config *hw = &wavefront_configuration;
- if (hw->opened) {
- printk (KERN_WARNING "WaveFront: warning: device in use\n");
- }
+ if (format == SYSEX_PATCH) { /* Handled by midi_synth.c */
+ if (midi_load_patch == NULL) {
+ printk (KERN_ERR LOGNAME
+ "SYSEX not loadable: "
+ "no midi patch loader!\n");
+ return -(EINVAL);
+ }
- hw->opened = mode;
- return (0);
-}
+ return midi_load_patch (devno, format, addr,
+ offs, count, pmgr_flag);
-static void wavefront_close (int dev)
-{
- struct wf_config *hw = &wavefront_configuration;
+ } else if (format == GUS_PATCH) {
+ return wavefront_load_gus_patch (devno, format,
+ addr, offs, count, pmgr_flag);
-#ifdef WF_STATS
- int i;
- printk ("Status during loop: %ld\n", hw->status_found_during_loop);
- for (i = 0; i < 4; i++) {
- printk ("Status during sleep[%d]: %ld\n",
- i, hw->status_found_during_sleep[i]);
+ } else if (format != WAVEFRONT_PATCH) {
+ printk (KERN_ERR LOGNAME "unknown patch format %d\n", format);
+ return -(EINVAL);
}
-#endif WF_STATS
- hw->opened = 0;
- hw->debug = 0;
- return;
-}
-
-static void wavefront_aftertouch (int dev, int channel, int pressure)
-{
- midi_synth_aftertouch (wavefront_configuration.mididev,channel,pressure);
-};
+ if (count < sizeof (wavefront_patch_info)) {
+ printk (KERN_ERR LOGNAME "sample header too short\n");
+ return -(EINVAL);
+ }
-static void wavefront_bender (int dev, int chn, int value)
-{
- midi_synth_bender (wavefront_configuration.mididev, chn, value);
-};
+ /* "addr" points to a user-space wavefront_patch_info */
-static void wavefront_controller (int dev, int channel, int ctrl_num, int value)
-{
- if(ctrl_num==CTRL_PITCH_BENDER) wavefront_bender(0,channel,value);
- midi_synth_controller (wavefront_configuration.mididev,
- channel,ctrl_num,value);
-};
+ return wavefront_load_patch (addr);
+}
-static void wavefront_panning(int dev, int channel, int pressure)
+static struct synth_operations wavefront_operations =
{
- midi_synth_controller (wavefront_configuration.mididev,
- channel,CTL_PAN,pressure);
+ "WaveFront",
+ &wavefront_info,
+ 0,
+ SYNTH_TYPE_SAMPLE,
+ SAMPLE_TYPE_WAVEFRONT,
+ wavefront_oss_open,
+ wavefront_oss_close,
+ wavefront_oss_ioctl,
+
+ midi_synth_kill_note,
+ midi_synth_start_note,
+ midi_synth_set_instr,
+ midi_synth_reset,
+ NULL, /* hw_control */
+ midi_synth_load_patch,
+ midi_synth_aftertouch,
+ midi_synth_controller,
+ midi_synth_panning,
+ NULL, /* volume method */
+ midi_synth_bender,
+ NULL, /* alloc voice */
+ midi_synth_setup_voice
};
+#endif OSS_SUPPORT_SEQ
-static int wavefront_set_instr (int dev, int channel, int instr_no)
-{
- return(midi_synth_set_instr (wavefront_configuration.mididev,
- channel,instr_no));
-};
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_STATIC_INSTALL
-static int wavefront_kill_note (int dev, int channel, int note, int volume)
-{
- if (note==255)
- return (midi_synth_start_note (wavefront_configuration.mididev,
- channel, 0, 0));
- return(midi_synth_kill_note (wavefront_configuration.mididev,
- channel, note, volume));
-};
+void attach_wavefront (struct address_info *hw_config)
-static int wavefront_start_note (int dev, int channel, int note, int volume)
{
- if (note==255) {
- midi_synth_aftertouch (wavefront_configuration.mididev,
- channel,volume);
- return(0);
- };
-
- if (volume==0) {
- volume=127;
- midi_synth_aftertouch
- (wavefront_configuration.mididev,
- channel,0);
- };
-
- midi_synth_start_note (wavefront_configuration.mididev,
- channel, note, volume);
- return(0);
-};
+ (void) install_wavefront ();
+}
-static void wavefront_setup_voice (int dev, int voice, int chn)
-{
-};
+int probe_wavefront (struct address_info *hw_config)
-static void wavefront_reset (int dev)
{
- int i;
-
- for (i = 0; i < 16; i++) {
- midi_synth_kill_note (dev,i,0,0);
- };
-};
+ return !detect_wavefront (hw_config->irq, hw_config->io_base);
+}
-static struct synth_operations wavefront_operations =
+void unload_wavefront (struct address_info *hw_config)
{
- "WaveFront",
- &wavefront_info,
- 0,
- SYNTH_TYPE_SAMPLE,
- SAMPLE_TYPE_WAVEFRONT,
- wavefront_open,
- wavefront_close,
- wavefront_ioctl,
- wavefront_kill_note,
- wavefront_start_note,
- wavefront_set_instr,
- wavefront_reset,
- NULL,
- wavefront_load_patch,
- wavefront_aftertouch,
- wavefront_controller,
- wavefront_panning,
- NULL,
- wavefront_bender,
- NULL,
- wavefront_setup_voice
-};
+ (void) uninstall_wavefront ();
+}
+#endif OSS_SUPPORT_STATIC_INSTALL
-/***********************************************************************
-WaveFront: OSS/Free and/or Linux kernel installation interface
-***********************************************************************/
+/***********************************************************************/
+/* WaveFront: Linux modular sound kernel installation interface */
+/***********************************************************************/
void
wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
{
- /* We don't use this handler except during device
- configuration. While the module is installed, the
- interrupt is used to signal MIDI interrupts, and is
- handled by the interrupt routine in wf_midi.c
- */
-
- wf_config *hw = (wf_config *) dev_id;
- hw->irq_ok = 1;
+ struct wf_config *hw = dev_id;
+
+ /*
+ Some comments on interrupts. I attempted a version of this
+ driver that used interrupts throughout the code instead of
+ doing busy and/or sleep-waiting. Alas, it appears that once
+ the Motorola firmware is downloaded, the card *never*
+ generates an RX interrupt. These are successfully generated
+ during firmware loading, and after that wavefront_status()
+ reports that an interrupt is pending on the card from time
+ to time, but it never seems to be delivered to this
+ driver. Note also that wavefront_status() continues to
+ report that RX interrupts are enabled, suggesting that I
+ didn't goof up and disable them by mistake.
+
+ Thus, I stepped back to a prior version of
+ wavefront_wait(), the only place where this really
+ matters. Its sad, but I've looked through the code to check
+ on things, and I really feel certain that the Motorola
+ firmware prevents RX-ready interrupts.
+ */
- if ((wavefront_status(hw) & STAT_INTR_WRITE) ||
- (wavefront_status(hw) & STAT_INTR_READ)) {
- wake_up (&hw->interrupt_sleeper);
+ if ((wavefront_status() & (STAT_INTR_READ|STAT_INTR_WRITE)) == 0) {
+ return;
}
+
+ hw->irq_ok = 1;
+ hw->irq_cnt++;
+ wake_up_interruptible (&hw->interrupt_sleeper);
}
/* STATUS REGISTER
@@ -2202,16 +2224,6 @@ wavefrontintr (int irq, void *dev_id, struct pt_regs *dummy)
5 Host Tx Register empty (1=Empty)
6 Host Tx Interrupt Pending (1=Interrupt)
7 Unused
-
-11111001
- Rx Intr enable
- nothing to read from board
- no rx interrupt pending
- unused
- tx interrupt enabled
- space to transmit
- tx interrupt pending
-
*/
int
@@ -2235,7 +2247,7 @@ wavefront_interrupt_bits (int irq)
break;
default:
- printk (KERN_WARNING "WaveFront: invalid IRQ %d\n", irq);
+ printk (KERN_WARNING LOGNAME "invalid IRQ %d\n", irq);
bits = -1;
}
@@ -2243,42 +2255,78 @@ wavefront_interrupt_bits (int irq)
}
void
-wavefront_should_cause_interrupt (wf_config *hw, int val, int port, int timeout)
+wavefront_should_cause_interrupt (int val, int port, int timeout)
{
unsigned long flags;
save_flags (flags);
cli();
- hw->irq_ok = 0;
+ dev.irq_ok = 0;
outb (val,port);
- interruptible_sleep_on_timeout(&hw->interrupt_sleeper, timeout);
+ interruptible_sleep_on_timeout (&dev.interrupt_sleeper, timeout);
restore_flags (flags);
}
static int
-wavefront_hw_reset (wf_config *hw)
+wavefront_hw_reset (void)
{
int bits;
int hwv[2];
+ unsigned long irq_mask;
+ short reported_irq;
+
+ /* IRQ already checked in init_module() */
+
+ bits = wavefront_interrupt_bits (dev.irq);
- /* Check IRQ is legal */
+ printk (KERN_DEBUG LOGNAME "autodetecting WaveFront IRQ\n");
- if ((bits = wavefront_interrupt_bits (hw->irq)) < 0) {
+ sti ();
+
+ irq_mask = probe_irq_on ();
+
+ outb (0x0, dev.control_port);
+ outb (0x80 | 0x40 | bits, dev.data_port);
+ wavefront_should_cause_interrupt(0x80|0x40|0x10|0x1,
+ dev.control_port,
+ (reset_time*HZ)/100);
+
+ reported_irq = probe_irq_off (irq_mask);
+
+ if (reported_irq != dev.irq) {
+ if (reported_irq == 0) {
+ printk (KERN_ERR LOGNAME
+ "No unassigned interrupts detected "
+ "after h/w reset\n");
+ } else if (reported_irq < 0) {
+ printk (KERN_ERR LOGNAME
+ "Multiple unassigned interrupts detected "
+ "after h/w reset\n");
+ } else {
+ printk (KERN_ERR LOGNAME "autodetected IRQ %d not the "
+ "value provided (%d)\n", reported_irq,
+ dev.irq);
+ }
+ dev.irq = -1;
return 1;
+ } else {
+ printk (KERN_INFO LOGNAME "autodetected IRQ at %d\n",
+ reported_irq);
}
- if (request_irq (hw->irq, wavefrontintr,
- 0, "WaveFront", (void *) hw) < 0) {
- printk (KERN_WARNING "WaveFront: IRQ %d not available!\n",
- hw->irq);
+ if (request_irq (dev.irq, wavefrontintr,
+ SA_INTERRUPT|SA_SHIRQ,
+ "wavefront synth", &dev) < 0) {
+ printk (KERN_WARNING LOGNAME "IRQ %d not available!\n",
+ dev.irq);
return 1;
}
/* try reset of port */
- outb (0x0, hw->control_port);
+ outb (0x0, dev.control_port);
/* At this point, the board is in reset, and the H/W initialization
register is accessed at the same address as the data port.
@@ -2291,8 +2339,8 @@ wavefront_hw_reset (wf_config *hw)
0 - Use the MIDI Input from the 26-pin WaveBlaster
compatible header as the serial MIDI source
- 1 - Use the MIDI Input from the 9-pin D connector as the serial MIDI
- source.
+ 1 - Use the MIDI Input from the 9-pin D connector as the
+ serial MIDI source.
Bits 5:3 - IRQ Selection
0 0 0 - IRQ 2/9
@@ -2316,7 +2364,7 @@ wavefront_hw_reset (wf_config *hw)
plus external 9-pin MIDI interface selected
*/
- outb (0x80 | 0x40 | bits, hw->data_port);
+ outb (0x80 | 0x40 | bits, dev.data_port);
/* CONTROL REGISTER
@@ -2329,85 +2377,28 @@ wavefront_hw_reset (wf_config *hw)
6 Master Interrupt Enable (1=Enabled) 0x40
7 Master Reset (0=Reset; 1=Run) 0x80
- Take us out of reset, unmute, master + TX + RX interrupts on.
+ Take us out of reset, mute output, master + TX + RX interrupts on.
We'll get an interrupt presumably to tell us that the TX
- register is clear. However, this doesn't mean that the
- board is ready. We actually have to send it a command, and
- wait till it gets back to use. After a cold boot, this can
- take some time.
-
- I think this is because its only after a cold boot that the
- onboard ROM does its memory check, which can take "up to 4
- seconds" according to the WaveFront SDK. So, since sleeping
- doesn't cost us much, we'll give it *plenty* of time. It
- turns out that with 12MB of RAM, it can take up to 16
- seconds or so!! See the code after "ABOUT INTERRUPTS"
+ register is clear.
*/
- wavefront_should_cause_interrupt(hw,
- 0x80|0x40|0x10|0x1,
- hw->control_port,
- (2*HZ)/100);
+ wavefront_should_cause_interrupt(0x80|0x40|0x10|0x1,
+ dev.control_port,
+ (reset_time*HZ)/100);
/* Note: data port is now the data port, not the h/w initialization
port.
*/
- if (!hw->irq_ok) {
- printk (KERN_WARNING
- "WaveFront: intr not received after h/w un-reset.\n");
+ if (!dev.irq_ok) {
+ printk (KERN_WARNING LOGNAME
+ "intr not received after h/w un-reset.\n");
goto gone_bad;
}
- hw->interrupts_on = 1;
+ dev.interrupts_on = 1;
- /* ABOUT INTERRUPTS:
- -----------------
-
- When we talk about interrupts, there are two kinds
- generated by the ICS2115. The first is to signal MPU data
- ready to read, and the second is to signal RX or TX status
- changes. We *always* want interrupts for MPU stuff but we
- generally avoid using RX/TX interrupts.
-
- In theory, we could use the TX and RX interrupts for all
- communication with the card. However, there are 2 good
- reasons not to do this.
-
- First of all, the MIDI interface is going to use the same
- interrupt. This presents no practical problem since Linux
- allows us to share IRQ's. However, there are times when it
- makes sense for a user to ask the driver to disable
- interrupts, to avoid bothering Linux with a stream of MIDI
- interrupts that aren't going to be used because nothing
- cares about them. If we rely on them for communication with
- the WaveFront synth as well, this disabling would be
- crippling. Since being able to disable them can save quite
- a bit of overhead (consider the interrupt frequency of a
- physical MIDI controller like a modwheel being shunted back
- and forth - its higher than the mouse, and much of
- the time is of absolutely no interest to the kernel or any
- user space processes whatsoever), we don't want to do this.
-
- Secondly, much of the time, there's no reason to go to
- sleep on a TX or RX status: the WaveFront gets back to us
- quickly enough that its a lot more efficient to just busy
- wait on the relevant status. Once we go to sleep, all is
- lost anyway, and so interrupts don't really help us much anyway.
-
- Therefore, we don't use interrupts for communication with
- the WaveFront synth. We just poll the relevant RX/TX status.
-
- However, there is one broad exception to this. During module
- loading, to deal with several situations where timing would
- be an issue, we use TX/RX interrupts to help us avoid busy
- waiting for indeterminate and hard to manage periods of
- time. So, TX/RX interrupts are enabled until the end of
- wavefront_init(), and not used again after that.
-
- */
-
/* Note: data port is now the data port, not the h/w initialization
port.
@@ -2421,27 +2412,27 @@ wavefront_hw_reset (wf_config *hw)
subsequent ISC2115 reboots (say, caused by module
reloading) will get through this much faster.
- Interesting question: why is no RX interrupt received first ?
+ XXX Interesting question: why is no RX interrupt received first ?
*/
-
- wavefront_should_cause_interrupt(hw, WFC_HARDWARE_VERSION,
- hw->data_port, 20*HZ);
- if (!hw->irq_ok) {
- printk (KERN_WARNING
- "WaveFront: post-RAM-check interrupt not received.\n");
+ wavefront_should_cause_interrupt(WFC_HARDWARE_VERSION,
+ dev.data_port, ramcheck_time*HZ);
+
+ if (!dev.irq_ok) {
+ printk (KERN_WARNING LOGNAME
+ "post-RAM-check interrupt not received.\n");
goto gone_bad;
}
- if (!(wavefront_status(hw) & STAT_CAN_READ)) {
- printk (KERN_WARNING
- "WaveFront: no response to HW version cmd.\n");
+ if (!wavefront_wait (STAT_CAN_READ)) {
+ printk (KERN_WARNING LOGNAME
+ "no response to HW version cmd.\n");
goto gone_bad;
}
- if ((hwv[0] = wavefront_read (hw)) == -1) {
- printk (KERN_WARNING
- "WaveFront: board not responding correctly.\n");
+ if ((hwv[0] = wavefront_read ()) == -1) {
+ printk (KERN_WARNING LOGNAME
+ "board not responding correctly.\n");
goto gone_bad;
}
@@ -2451,13 +2442,11 @@ wavefront_hw_reset (wf_config *hw)
and tell us about it either way.
*/
- if ((hwv[0] = wavefront_read (hw)) == -1) {
- printk (KERN_WARNING
- "WaveFront: on-board RAM test failed "
+ if ((hwv[0] = wavefront_read ()) == -1) {
+ printk (KERN_WARNING LOGNAME "on-board RAM test failed "
"(bad error code).\n");
} else {
- printk (KERN_WARNING
- "WaveFront: on-board RAM test failed "
+ printk (KERN_WARNING LOGNAME "on-board RAM test failed "
"(error code: 0x%x).\n",
hwv[0]);
}
@@ -2466,85 +2455,66 @@ wavefront_hw_reset (wf_config *hw)
/* We're OK, just get the next byte of the HW version response */
- if ((hwv[1] = wavefront_read (hw)) == -1) {
- printk (KERN_WARNING
- "WaveFront: board not responding correctly(2).\n");
+ if ((hwv[1] = wavefront_read ()) == -1) {
+ printk (KERN_WARNING LOGNAME "incorrect h/w response.\n");
goto gone_bad;
}
- printk (KERN_INFO "WaveFront: hardware version %d.%d\n",
+ printk (KERN_INFO LOGNAME "hardware version %d.%d\n",
hwv[0], hwv[1]);
return 0;
gone_bad:
- free_irq (hw->irq, hw);
- return (1);
+ if (dev.irq >= 0) {
+ free_irq (dev.irq, &dev);
+ dev.irq = -1;
}
+ return (1);
+}
-int
-probe_wavefront (struct address_info *hw_config)
+__initfunc (static int detect_wavefront (int irq, int io_base))
{
unsigned char rbuf[4], wbuf[4];
- wf_config *hw;
- if (hw_config->irq < 0 || hw_config->irq > 16) {
- printk (KERN_WARNING "WaveFront: impossible IRQ suggested(%d)\n",
- hw_config->irq);
- return 0;
- }
-
- /* Yeah yeah, TB docs say 8, but the FX device on the Tropez Plus
- takes up another 8 ...
+ /* TB docs say the device takes up 8 ports, but we know that
+ if there is an FX device present (i.e. a Tropez+) it really
+ consumes 16.
*/
- if (check_region (hw_config->io_base, 16)) {
- printk (KERN_ERR "WaveFront: IO address range 0x%x - 0x%x "
- "already in use - ignored\n", hw_config->io_base,
- hw_config->io_base+15);
- return 0;
+ if (check_region (io_base, 16)) {
+ printk (KERN_ERR LOGNAME "IO address range 0x%x - 0x%x "
+ "already in use - ignored\n", dev.base,
+ dev.base+15);
+ return -1;
}
- hw = &wavefront_configuration;
-
- hw->irq = hw_config->irq;
- hw->base = hw_config->io_base;
-
- hw->israw = 0;
- hw->debug = debug_default;
- hw->interrupts_on = 0;
- hw->rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
-
-#ifdef WF_STATS
- hw->status_found_during_sleep[0] = 0;
- hw->status_found_during_sleep[1] = 0;
- hw->status_found_during_sleep[2] = 0;
- hw->status_found_during_sleep[3] = 0;
- hw->status_found_during_loop = 0;
-#endif WF_STATS
-
- hw_config->slots[WF_SYNTH_SLOT] = hw->synthdev = -1;
- hw_config->slots[WF_INTERNAL_MIDI_SLOT] = hw->mididev = -1;
- hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = hw->ext_mididev = -1;
-
- if (wavefront_cmd (hw, WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
-
- hw->fw_version[0] = rbuf[0];
- hw->fw_version[1] = rbuf[1];
- printk (KERN_INFO
- "WaveFront: firmware %d.%d already loaded.\n",
+ dev.irq = irq;
+ dev.base = io_base;
+ dev.israw = 0;
+ dev.debug = debug_default;
+ dev.interrupts_on = 0;
+ dev.irq_cnt = 0;
+ dev.rom_samples_rdonly = 1; /* XXX default lock on ROM sample slots */
+
+ if (wavefront_cmd (WFC_FIRMWARE_VERSION, rbuf, wbuf) == 0) {
+
+ dev.fw_version[0] = rbuf[0];
+ dev.fw_version[1] = rbuf[1];
+ printk (KERN_INFO LOGNAME
+ "firmware %d.%d already loaded.\n",
rbuf[0], rbuf[1]);
/* check that a command actually works */
- if (wavefront_cmd (hw, WFC_HARDWARE_VERSION,
+ if (wavefront_cmd (WFC_HARDWARE_VERSION,
rbuf, wbuf) == 0) {
- hw->hw_version[0] = rbuf[0];
- hw->hw_version[1] = rbuf[1];
+ dev.hw_version[0] = rbuf[0];
+ dev.hw_version[1] = rbuf[1];
} else {
- printk (KERN_INFO "WaveFront: not raw, but no "
+ printk (KERN_WARNING LOGNAME "not raw, but no "
"hardware version!\n");
return 0;
}
@@ -2552,25 +2522,30 @@ probe_wavefront (struct address_info *hw_config)
if (!wf_raw) {
return 1;
} else {
- printk (KERN_INFO
- "WaveFront: reloading firmware anyway.\n");
+ printk (KERN_INFO LOGNAME
+ "reloading firmware anyway.\n");
+ dev.israw = 1;
}
} else {
- hw->israw = 1;
- printk (KERN_INFO "WaveFront: no response to firmware probe, "
- "assume raw.\n");
+ dev.israw = 1;
+ printk (KERN_INFO LOGNAME
+ "no response to firmware probe, assume raw.\n");
}
- init_waitqueue (&hw->interrupt_sleeper);
+ init_waitqueue (&dev.interrupt_sleeper);
- if (wavefront_hw_reset (hw)) {
- printk (KERN_WARNING "WaveFront: hardware reset failed\n");
+ if (wavefront_hw_reset ()) {
+ printk (KERN_WARNING LOGNAME "hardware reset failed\n");
return 0;
}
+ /* Check for FX device, present only on Tropez+ */
+
+ dev.has_fx = (detect_wffx () == 0);
+
return 1;
}
@@ -2585,7 +2560,7 @@ probe_wavefront (struct address_info *hw_config)
static int errno;
static int
-wavefront_download_firmware (wf_config *hw, char *path)
+wavefront_download_firmware (char *path)
{
unsigned char section[WF_SECTION_MAX];
@@ -2610,7 +2585,7 @@ wavefront_download_firmware (wf_config *hw, char *path)
set_fs (get_ds());
if ((fd = open (path, 0, 0)) < 0) {
- printk (KERN_WARNING "WaveFront: Unable to load \"%s\".\n",
+ printk (KERN_WARNING LOGNAME "Unable to load \"%s\".\n",
path);
return 1;
}
@@ -2620,7 +2595,7 @@ wavefront_download_firmware (wf_config *hw, char *path)
if ((x = read (fd, &section_length, sizeof (section_length))) !=
sizeof (section_length)) {
- printk (KERN_ERR "WaveFront: firmware read error.\n");
+ printk (KERN_ERR LOGNAME "firmware read error.\n");
goto failure;
}
@@ -2629,58 +2604,46 @@ wavefront_download_firmware (wf_config *hw, char *path)
}
if (read (fd, section, section_length) != section_length) {
- printk (KERN_ERR "WaveFront: firmware section "
+ printk (KERN_ERR LOGNAME "firmware section "
"read error.\n");
goto failure;
}
/* Send command */
- if (!wavefront_write (hw, WFC_DOWNLOAD_OS)) {
+ if (wavefront_write (WFC_DOWNLOAD_OS)) {
goto failure;
}
for (i = 0; i < section_length; i++) {
- if (!wavefront_write (hw, section[i])) {
+ if (wavefront_write (section[i])) {
goto failure;
}
}
/* get ACK */
- if (wavefront_wait (hw, STAT_CAN_READ)) {
+ if (wavefront_wait (STAT_CAN_READ)) {
- if ((c = inb (hw->data_port)) != WF_ACK) {
+ if ((c = inb (dev.data_port)) != WF_ACK) {
- printk (KERN_ERR "WaveFront: download "
+ printk (KERN_ERR LOGNAME "download "
"of section #%d not "
"acknowledged, ack = 0x%x\n",
section_cnt_downloaded + 1, c);
goto failure;
- } else {
-#ifdef WF_DEBUG
- if ((hw->debug & WF_DEBUG_IO) &&
- !(++section_cnt_downloaded % 10)) {
- printk (KERN_DEBUG ".");
- }
-#endif WF_DEBUG
}
} else {
- printk (KERN_ERR "WaveFront: timed out "
- "for download ACK.\n");
+ printk (KERN_ERR LOGNAME "time out for firmware ACK.\n");
+ goto failure;
}
}
close (fd);
set_fs (fs);
-#ifdef WF_DEBUG
- if (hw->debug & WF_DEBUG_IO) {
- printk (KERN_DEBUG "\n");
- }
-#endif WF_DEBUG
return 0;
failure:
@@ -2690,38 +2653,33 @@ wavefront_download_firmware (wf_config *hw, char *path)
return 1;
}
-static int
-wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
+__initfunc (static int wavefront_config_midi (void))
{
unsigned char rbuf[4], wbuf[4];
- if (!probe_wf_mpu (hw_config)) {
- printk (KERN_WARNING "WaveFront: could not install "
- "MPU-401 device.\n");
- return 1;
+ if (detect_wf_mpu (dev.irq, dev.base) < 0) {
+ printk (KERN_WARNING LOGNAME
+ "could not find working MIDI device\n");
+ return -1;
}
- /* Attach an modified MPU-401 driver to the master MIDI interface */
-
- hw_config->name = "WaveFront Internal MIDI";
- attach_wf_mpu (hw_config);
-
- if (hw_config->slots[WF_INTERNAL_MIDI_SLOT] == -1) {
- printk (KERN_WARNING "WaveFront: MPU-401 not configured.\n");
- return 1;
+ if ((dev.mididev = install_wf_mpu ()) < 0) {
+ printk (KERN_WARNING LOGNAME
+ "MIDI interfaces not configured\n");
+ return -1;
}
- hw->mididev = hw_config->slots[WF_INTERNAL_MIDI_SLOT];
-
/* Route external MIDI to WaveFront synth (by default) */
- if (wavefront_cmd (hw, WFC_MISYNTH_ON, rbuf, wbuf)) {
- printk (KERN_WARNING
- "WaveFront: cannot enable MIDI-IN to synth routing.\n");
+ if (wavefront_cmd (WFC_MISYNTH_ON, rbuf, wbuf)) {
+ printk (KERN_WARNING LOGNAME
+ "cannot enable MIDI-IN to synth routing.\n");
/* XXX error ? */
}
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
/* Get the regular MIDI patch loading function, so we can
use it if we ever get handed a SYSEX patch. This is
unlikely, because its so damn slow, but we may as well
@@ -2730,12 +2688,14 @@ wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
only use MIDI to do patch loading.
*/
- if (midi_devs[hw->mididev]->converter != NULL) {
- midi_load_patch = midi_devs[hw->mididev]->converter->load_patch;
- midi_devs[hw->mididev]->converter->load_patch =
- &wavefront_load_patch;
+ if (midi_devs[dev.mididev]->converter != NULL) {
+ midi_load_patch = midi_devs[dev.mididev]->converter->load_patch;
+ midi_devs[dev.mididev]->converter->load_patch =
+ &wavefront_oss_load_patch;
}
+#endif OSS_SUPPORT_SEQ
+
/* Turn on Virtual MIDI, but first *always* turn it off,
since otherwise consectutive reloads of the driver will
never cause the hardware to generate the initial "internal" or
@@ -2747,22 +2707,19 @@ wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
the internal interface. Duh.
*/
- if (wavefront_cmd (hw, WFC_VMIDI_OFF, rbuf, wbuf)) {
- printk (KERN_WARNING "WaveFront: cannot disable "
- "virtual MIDI mode\n");
- /* XXX go ahead and try anyway ? */
+ if (wavefront_cmd (WFC_VMIDI_OFF, rbuf, wbuf)) {
+ printk (KERN_WARNING LOGNAME
+ "virtual MIDI mode not disabled\n");
+ return 0; /* We're OK, but missing the external MIDI dev */
}
- hw_config->name = "WaveFront External MIDI";
-
- if (virtual_midi_enable (hw->mididev, hw_config)) {
- printk (KERN_WARNING "WaveFront: no virtual MIDI access.\n");
+ if ((dev.ext_mididev = virtual_midi_enable ()) < 0) {
+ printk (KERN_WARNING LOGNAME "no virtual MIDI access.\n");
} else {
- hw->ext_mididev = hw_config->slots[WF_EXTERNAL_MIDI_SLOT];
- if (wavefront_cmd (hw, WFC_VMIDI_ON, rbuf, wbuf)) {
- printk (KERN_WARNING
- "WaveFront: cannot enable virtual MIDI mode.\n");
- virtual_midi_disable (hw->mididev);
+ if (wavefront_cmd (WFC_VMIDI_ON, rbuf, wbuf)) {
+ printk (KERN_WARNING LOGNAME
+ "cannot enable virtual MIDI mode.\n");
+ virtual_midi_disable ();
}
}
@@ -2770,62 +2727,66 @@ wavefront_config_midi (wf_config *hw, struct address_info *hw_config)
}
static int
-wavefront_do_reset (wf_config *hw, int atboot)
+wavefront_do_reset (int atboot)
{
char voices[1];
- if (!atboot && wavefront_hw_reset (hw)) {
- printk (KERN_WARNING "WaveFront: hw reset failed.\n");
+ if (!atboot && wavefront_hw_reset ()) {
+ printk (KERN_WARNING LOGNAME "hw reset failed.\n");
goto gone_bad;
}
- if (hw->israw || wf_raw) {
- if (wavefront_download_firmware (hw, ospath)) {
+ if (dev.israw) {
+ if (wavefront_download_firmware (ospath)) {
goto gone_bad;
}
+ dev.israw = 0;
+
/* Wait for the OS to get running. The protocol for
this is non-obvious, and was determined by
using port-IO tracing in DOSemu and some
experimentation here.
- Rather than busy-wait, use interrupts creatively.
+ Rather than using timed waits, use interrupts creatively.
*/
- wavefront_should_cause_interrupt (hw, WFC_NOOP,
- hw->data_port, (10*HZ));
-
- if (!hw->irq_ok) {
- printk (KERN_WARNING
- "WaveFront: no post-OS interrupt.\n");
+ wavefront_should_cause_interrupt (WFC_NOOP,
+ dev.data_port,
+ (osrun_time*HZ));
+
+ if (!dev.irq_ok) {
+ printk (KERN_WARNING LOGNAME
+ "no post-OS interrupt.\n");
goto gone_bad;
}
/* Now, do it again ! */
- wavefront_should_cause_interrupt (hw, WFC_NOOP,
- hw->data_port, (10*HZ));
+ wavefront_should_cause_interrupt (WFC_NOOP,
+ dev.data_port, (10*HZ));
- if (!hw->irq_ok) {
- printk (KERN_WARNING
- "WaveFront: no post-OS interrupt(2).\n");
+ if (!dev.irq_ok) {
+ printk (KERN_WARNING LOGNAME
+ "no post-OS interrupt(2).\n");
goto gone_bad;
}
/* OK, no (RX/TX) interrupts any more, but leave mute
- on. Master interrupts get enabled when we're done here.
+ in effect.
*/
- outb (0x80, hw->control_port);
-
+ outb (0x80|0x40, dev.control_port);
+
/* No need for the IRQ anymore */
- free_irq (hw->irq, hw);
+ free_irq (dev.irq, &dev);
+
}
- if (/*XXX has_fx_device() && */ fx_raw) {
- wffx_init (hw);
+ if (dev.has_fx && fx_raw) {
+ wffx_init ();
}
/* SETUPSND.EXE asks for sample memory config here, but since i
@@ -2833,118 +2794,130 @@ wavefront_do_reset (wf_config *hw, int atboot)
about it.
*/
- if ((hw->freemem = wavefront_freemem (hw)) < 0) {
+ if ((dev.freemem = wavefront_freemem ()) < 0) {
goto gone_bad;
}
- printk (KERN_INFO "WaveFront: available DRAM %dk\n", hw->freemem / 1024);
+ printk (KERN_INFO LOGNAME "available DRAM %dk\n", dev.freemem / 1024);
- if (!wavefront_write (hw, 0xf0) ||
- !wavefront_write (hw, 1) ||
- (wavefront_read (hw) < 0)) {
- hw->debug = 0;
- printk (KERN_WARNING "WaveFront: MPU emulation mode not set.\n");
+ if (wavefront_write (0xf0) ||
+ wavefront_write (1) ||
+ (wavefront_read () < 0)) {
+ dev.debug = 0;
+ printk (KERN_WARNING LOGNAME "MPU emulation mode not set.\n");
goto gone_bad;
}
voices[0] = 32;
- if (wavefront_cmd (hw, WFC_SET_NVOICES, 0, voices)) {
- printk (KERN_WARNING
- "WaveFront: cannot set number of voices to 32.\n");
+ if (wavefront_cmd (WFC_SET_NVOICES, 0, voices)) {
+ printk (KERN_WARNING LOGNAME
+ "cannot set number of voices to 32.\n");
+ goto gone_bad;
}
+
return 0;
gone_bad:
/* reset that sucker so that it doesn't bother us. */
- outb (0x0, hw->control_port);
- free_irq (hw->irq, hw);
+ outb (0x0, dev.control_port);
+ dev.interrupts_on = 0;
+ if (dev.irq >= 0) {
+ free_irq (dev.irq, &dev);
+ }
return 1;
}
static int
-wavefront_init (wf_config *hw, int atboot)
+wavefront_init (int atboot)
{
int samples_are_from_rom;
- if (hw->israw || wf_raw) {
+ if (dev.israw) {
samples_are_from_rom = 1;
} else {
+ /* XXX is this always true ? */
samples_are_from_rom = 0;
}
- if (hw->israw || wf_raw || fx_raw) {
- if (wavefront_do_reset (hw, atboot)) {
- return 1;
+ if (dev.israw || fx_raw) {
+ if (wavefront_do_reset (atboot)) {
+ return -1;
}
}
- wavefront_get_sample_status (hw, samples_are_from_rom);
- wavefront_get_program_status (hw);
- wavefront_get_patch_status (hw);
+ wavefront_get_sample_status (samples_are_from_rom);
+ wavefront_get_program_status ();
+ wavefront_get_patch_status ();
- /* Start normal operation: unreset, master interrupt enable
- (for MPU interrupts) no mute
+ /* Start normal operation: unreset, master interrupt enabled, no mute
*/
- outb (0x80|0x40|0x20, hw->control_port);
+ outb (0x80|0x40|0x20, dev.control_port);
return (0);
}
-void
-attach_wavefront (struct address_info *hw_config)
+__initfunc (static int install_wavefront (void))
+
{
- int i;
- struct wf_config *hw = &wavefront_configuration;
+ if ((dev.synth_dev = register_sound_synth (&wavefront_fops, -1)) < 0) {
+ printk (KERN_ERR LOGNAME "cannot register raw synth\n");
+ return -1;
+ }
- if ((i = sound_alloc_synthdev()) == -1) {
- printk (KERN_ERR "WaveFront: Too many synthesizers\n");
- return;
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+ if ((dev.oss_dev = sound_alloc_synthdev()) == -1) {
+ printk (KERN_ERR LOGNAME "Too many sequencers\n");
+ return -1;
} else {
- hw_config->slots[WF_SYNTH_SLOT] = i;
- hw->synthdev = i;
- synth_devs[hw->synthdev] = &wavefront_operations;
+ synth_devs[dev.oss_dev] = &wavefront_operations;
}
+#endif OSS_SUPPORT_SEQ
- if (wavefront_init (hw, 1)) {
- printk (KERN_WARNING "WaveFront: board could not "
- "be initialized.\n");
- sound_unload_synthdev (i);
- return;
+ if (wavefront_init (1) < 0) {
+ printk (KERN_WARNING LOGNAME "initialization failed.\n");
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+ sound_unload_synthdev (dev.oss_dev);
+#endif OSS_SUPPORT_SEQ
+
+ return -1;
}
- request_region (hw_config->io_base+2, 6, "WaveFront synth");
- request_region (hw_config->io_base+8, 8, "WaveFront FX");
+ request_region (dev.base+2, 6, "wavefront synth");
- conf_printf2 ("WaveFront Synth", hw_config->io_base, 0, -1, -1);
+ if (dev.has_fx) {
+ request_region (dev.base+8, 8, "wavefront fx");
+ }
-#if defined(CONFIG_MIDI)
- if (wavefront_config_midi (hw, hw_config)) {
- printk (KERN_WARNING "WaveFront: could not initialize MIDI.\n");
+ if (wavefront_config_midi ()) {
+ printk (KERN_WARNING LOGNAME "could not initialize MIDI.\n");
}
-#else
- printk (KERN_WARNING
- "WaveFront: MIDI not configured at kernel-config time.\n");
-#endif CONFIG_MIDI
- return;
+ return dev.oss_dev;
}
+
void
-unload_wavefront (struct address_info *hw_config)
+uninstall_wavefront (void)
+
{
- struct wf_config *hw = &wavefront_configuration;
-
- /* the first two are freed by the wf_mpu code */
- release_region (hw->base+2, 6);
- release_region (hw->base+8, 8);
- sound_unload_synthdev (hw->synthdev);
-#if defined(CONFIG_MIDI)
- unload_wf_mpu (hw_config);
-#endif
+ /* the first two i/o addresses are freed by the wf_mpu code */
+ release_region (dev.base+2, 6);
+
+ if (dev.has_fx) {
+ release_region (dev.base+8, 8);
+ }
+
+ unregister_sound_synth (dev.synth_dev);
+
+#if OSS_SUPPORT_LEVEL & OSS_SUPPORT_SEQ
+ sound_unload_synthdev (dev.oss_dev);
+#endif OSS_SUPPORT_SEQ
+ uninstall_wf_mpu ();
}
/***********************************************************************/
@@ -2961,83 +2934,111 @@ unload_wavefront (struct address_info *hw_config)
#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */
static int
-wffx_idle (struct wf_config *hw)
+wffx_idle (void)
{
int i;
unsigned int x = 0x80;
for (i = 0; i < 1000; i++) {
- x = inb (hw->fx_status);
+ x = inb (dev.fx_status);
if ((x & 0x80) == 0) {
break;
}
}
if (x & 0x80) {
- printk (KERN_ERR "WaveFront: FX device never idle.\n");
+ printk (KERN_ERR LOGNAME "FX device never idle.\n");
return 0;
}
return (1);
}
+__initfunc (static int detect_wffx (void))
+
+{
+ /* This is a crude check, but its the best one I have for now.
+ Certainly on the Maui and the Tropez, wffx_idle() will
+ report "never idle", which suggests that this test should
+ work OK.
+ */
+
+ if (inb (dev.fx_status) & 0x80) {
+ printk (KERN_INFO LOGNAME "Hmm, probably a Maui or Tropez.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+__initfunc (static int attach_wffx (void))
+
+{
+ if ((dev.fx_mididev = sound_alloc_mididev ()) < 0) {
+ printk (KERN_WARNING LOGNAME "cannot install FX Midi driver\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static void
-wffx_mute (struct wf_config *hw, int onoff)
+wffx_mute (int onoff)
{
- if (!wffx_idle(hw)) {
+ if (!wffx_idle()) {
return;
}
- outb (onoff ? 0x02 : 0x00, hw->fx_op);
+ outb (onoff ? 0x02 : 0x00, dev.fx_op);
}
static int
-wffx_memset (struct wf_config *hw, int page,
+wffx_memset (int page,
int addr, int cnt, unsigned short *data)
{
if (page < 0 || page > 7) {
- printk (KERN_ERR "WaveFront: FX memset: "
+ printk (KERN_ERR LOGNAME "FX memset: "
"page must be >= 0 and <= 7\n");
return -(EINVAL);
}
if (addr < 0 || addr > 0x7f) {
- printk (KERN_ERR "WaveFront: FX memset: "
+ printk (KERN_ERR LOGNAME "FX memset: "
"addr must be >= 0 and <= 7f\n");
return -(EINVAL);
}
if (cnt == 1) {
- outb (FX_LSB_TRANSFER, hw->fx_lcr);
- outb (page, hw->fx_dsp_page);
- outb (addr, hw->fx_dsp_addr);
- outb ((data[0] >> 8), hw->fx_dsp_msb);
- outb ((data[0] & 0xff), hw->fx_dsp_lsb);
+ outb (FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (page, dev.fx_dsp_page);
+ outb (addr, dev.fx_dsp_addr);
+ outb ((data[0] >> 8), dev.fx_dsp_msb);
+ outb ((data[0] & 0xff), dev.fx_dsp_lsb);
- printk (KERN_INFO "WaveFront: FX: addr %d:%x set to 0x%x\n",
+ printk (KERN_INFO LOGNAME "FX: addr %d:%x set to 0x%x\n",
page, addr, data[0]);
} else {
int i;
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (page, hw->fx_dsp_page);
- outb (addr, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (page, dev.fx_dsp_page);
+ outb (addr, dev.fx_dsp_addr);
for (i = 0; i < cnt; i++) {
- outb ((data[i] >> 8), hw->fx_dsp_msb);
- outb ((data[i] & 0xff), hw->fx_dsp_lsb);
- if (!wffx_idle (hw)) {
+ outb ((data[i] >> 8), dev.fx_dsp_msb);
+ outb ((data[i] & 0xff), dev.fx_dsp_lsb);
+ if (!wffx_idle ()) {
break;
}
}
if (i != cnt) {
- printk (KERN_WARNING
- "WaveFront: FX memset "
+ printk (KERN_WARNING LOGNAME
+ "FX memset "
"(0x%x, 0x%x, 0x%x, %d) incomplete\n",
page, addr, (int) data, cnt);
return -(EIO);
@@ -3048,7 +3049,7 @@ wffx_memset (struct wf_config *hw, int page,
}
static int
-wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
+wffx_ioctl (wavefront_fx_info *r)
{
unsigned short page_data[256];
@@ -3056,20 +3057,20 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
switch (r->request) {
case WFFX_MUTE:
- wffx_mute (hw, r->data[0]);
+ wffx_mute (r->data[0]);
return 0;
case WFFX_MEMSET:
if (r->data[2] <= 0) {
- printk (KERN_ERR "WaveFront: cannot write "
+ printk (KERN_ERR LOGNAME "cannot write "
"<= 0 bytes to FX\n");
return -(EINVAL);
} else if (r->data[2] == 1) {
pd = (unsigned short *) &r->data[3];
} else {
if (r->data[2] > sizeof (page_data)) {
- printk (KERN_ERR "WaveFront: cannot write "
+ printk (KERN_ERR LOGNAME "cannot write "
"> 255 bytes to FX\n");
return -(EINVAL);
}
@@ -3078,15 +3079,14 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
pd = page_data;
}
- return wffx_memset (hw,
- r->data[0], /* page */
+ return wffx_memset (r->data[0], /* page */
r->data[1], /* addr */
r->data[2], /* cnt */
pd);
default:
- printk (KERN_WARNING
- "WaveFront: FX: ioctl %d not yet supported\n",
+ printk (KERN_WARNING LOGNAME
+ "FX: ioctl %d not yet supported\n",
r->request);
return -(EINVAL);
}
@@ -3107,7 +3107,7 @@ wffx_ioctl (struct wf_config *hw, wavefront_fx_info *r)
*/
static int
-wffx_init (struct wf_config *hw)
+wffx_init (void)
{
int i;
@@ -3119,147 +3119,147 @@ wffx_init (struct wf_config *hw)
for (j = 0; j < 2; j++) {
for (i = 0x10; i <= 0xff; i++) {
- if (!wffx_idle (hw)) {
+ if (!wffx_idle ()) {
return (-1);
}
- outb (i, hw->fx_mod_addr);
- outb (0x0, hw->fx_mod_data);
+ outb (i, dev.fx_mod_addr);
+ outb (0x0, dev.fx_mod_data);
}
}
- if (!wffx_idle(hw)) return (-1);
- outb (0x02, hw->fx_op); /* mute on */
-
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x44, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x42, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x43, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x7c, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x7e, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x46, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x49, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x47, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x4a, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x02, dev.fx_op); /* mute on */
+
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x44, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x42, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x43, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x7c, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x7e, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x46, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x49, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x47, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x4a, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
/* either because of stupidity by TB's programmers, or because it
actually does something, rezero the MOD page.
*/
for (i = 0x10; i <= 0xff; i++) {
- if (!wffx_idle (hw)) {
+ if (!wffx_idle ()) {
return (-1);
}
- outb (i, hw->fx_mod_addr);
- outb (0x0, hw->fx_mod_data);
+ outb (i, dev.fx_mod_addr);
+ outb (0x0, dev.fx_mod_data);
}
/* load page zero */
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x00, hw->fx_dsp_page);
- outb (0x00, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x00, dev.fx_dsp_page);
+ outb (0x00, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_zero); i += 2) {
- outb (page_zero[i], hw->fx_dsp_msb);
- outb (page_zero[i+1], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_zero[i], dev.fx_dsp_msb);
+ outb (page_zero[i+1], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
/* Now load page one */
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x01, hw->fx_dsp_page);
- outb (0x00, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x01, dev.fx_dsp_page);
+ outb (0x00, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_one); i += 2) {
- outb (page_one[i], hw->fx_dsp_msb);
- outb (page_one[i+1], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_one[i], dev.fx_dsp_msb);
+ outb (page_one[i+1], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x02, hw->fx_dsp_page);
- outb (0x00, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x02, dev.fx_dsp_page);
+ outb (0x00, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_two); i++) {
- outb (page_two[i], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_two[i], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x03, hw->fx_dsp_page);
- outb (0x00, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x03, dev.fx_dsp_page);
+ outb (0x00, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_three); i++) {
- outb (page_three[i], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_three[i], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x04, hw->fx_dsp_page);
- outb (0x00, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x04, dev.fx_dsp_page);
+ outb (0x00, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_four); i++) {
- outb (page_four[i], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_four[i], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
/* Load memory area (page six) */
- outb (FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x06, hw->fx_dsp_page);
+ outb (FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x06, dev.fx_dsp_page);
for (i = 0; i < sizeof (page_six); i += 3) {
- outb (page_six[i], hw->fx_dsp_addr);
- outb (page_six[i+1], hw->fx_dsp_msb);
- outb (page_six[i+2], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_six[i], dev.fx_dsp_addr);
+ outb (page_six[i+1], dev.fx_dsp_msb);
+ outb (page_six[i+2], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x07, hw->fx_dsp_page);
- outb (0x00, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x00, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_seven); i += 2) {
- outb (page_seven[i], hw->fx_dsp_msb);
- outb (page_seven[i+1], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_seven[i], dev.fx_dsp_msb);
+ outb (page_seven[i+1], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
/* Now setup the MOD area. We do this algorithmically in order to
@@ -3268,192 +3268,192 @@ wffx_init (struct wf_config *hw)
*/
for (i = 0x00; i <= 0x0f; i++) {
- outb (0x01, hw->fx_mod_addr);
- outb (i, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
- outb (0x02, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x01, dev.fx_mod_addr);
+ outb (i, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
+ outb (0x02, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0xb0; i <= 0xbf; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x20, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x20, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0xf0; i <= 0xff; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x20, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x20, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0x10; i <= 0x1d; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0xff, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0xff, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0x1e, hw->fx_mod_addr);
- outb (0x40, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x1e, dev.fx_mod_addr);
+ outb (0x40, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
for (i = 0x1f; i <= 0x2d; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0xff, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0xff, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0x2e, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x2e, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
for (i = 0x2f; i <= 0x3e; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0x3f, hw->fx_mod_addr);
- outb (0x20, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x3f, dev.fx_mod_addr);
+ outb (0x20, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
for (i = 0x40; i <= 0x4d; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0x4e, hw->fx_mod_addr);
- outb (0x0e, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
- outb (0x4f, hw->fx_mod_addr);
- outb (0x0e, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x4e, dev.fx_mod_addr);
+ outb (0x0e, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
+ outb (0x4f, dev.fx_mod_addr);
+ outb (0x0e, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
for (i = 0x50; i <= 0x6b; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0x6c, hw->fx_mod_addr);
- outb (0x40, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x6c, dev.fx_mod_addr);
+ outb (0x40, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
- outb (0x6d, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x6d, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
- outb (0x6e, hw->fx_mod_addr);
- outb (0x40, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x6e, dev.fx_mod_addr);
+ outb (0x40, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
- outb (0x6f, hw->fx_mod_addr);
- outb (0x40, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x6f, dev.fx_mod_addr);
+ outb (0x40, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
for (i = 0x70; i <= 0x7f; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0xc0, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0xc0, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0x80; i <= 0xaf; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0xc0; i <= 0xdd; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0xde, hw->fx_mod_addr);
- outb (0x10, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
- outb (0xdf, hw->fx_mod_addr);
- outb (0x10, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0xde, dev.fx_mod_addr);
+ outb (0x10, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
+ outb (0xdf, dev.fx_mod_addr);
+ outb (0x10, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
for (i = 0xe0; i <= 0xef; i++) {
- outb (i, hw->fx_mod_addr);
- outb (0x00, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_mod_addr);
+ outb (0x00, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0x00; i <= 0x0f; i++) {
- outb (0x01, hw->fx_mod_addr);
- outb (i, hw->fx_mod_data);
- outb (0x02, hw->fx_mod_addr);
- outb (0x01, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (0x01, dev.fx_mod_addr);
+ outb (i, dev.fx_mod_data);
+ outb (0x02, dev.fx_mod_addr);
+ outb (0x01, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
- outb (0x02, hw->fx_op); /* mute on */
+ outb (0x02, dev.fx_op); /* mute on */
/* Now set the coefficients and so forth for the programs above */
for (i = 0; i < sizeof (coefficients); i += 4) {
- outb (coefficients[i], hw->fx_dsp_page);
- outb (coefficients[i+1], hw->fx_dsp_addr);
- outb (coefficients[i+2], hw->fx_dsp_msb);
- outb (coefficients[i+3], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (coefficients[i], dev.fx_dsp_page);
+ outb (coefficients[i+1], dev.fx_dsp_addr);
+ outb (coefficients[i+2], dev.fx_dsp_msb);
+ outb (coefficients[i+3], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
/* Some settings (?) that are too small to bundle into loops */
- if (!wffx_idle(hw)) return (-1);
- outb (0x1e, hw->fx_mod_addr);
- outb (0x14, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
- outb (0xde, hw->fx_mod_addr);
- outb (0x20, hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
- outb (0xdf, hw->fx_mod_addr);
- outb (0x20, hw->fx_mod_data);
+ if (!wffx_idle()) return (-1);
+ outb (0x1e, dev.fx_mod_addr);
+ outb (0x14, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
+ outb (0xde, dev.fx_mod_addr);
+ outb (0x20, dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
+ outb (0xdf, dev.fx_mod_addr);
+ outb (0x20, dev.fx_mod_data);
/* some more coefficients */
- if (!wffx_idle(hw)) return (-1);
- outb (0x06, hw->fx_dsp_page);
- outb (0x78, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x40, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x03, hw->fx_dsp_addr);
- outb (0x0f, hw->fx_dsp_msb);
- outb (0xff, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x0b, hw->fx_dsp_addr);
- outb (0x0f, hw->fx_dsp_msb);
- outb (0xff, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x02, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x0a, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x46, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
- outb (0x07, hw->fx_dsp_page);
- outb (0x49, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x06, dev.fx_dsp_page);
+ outb (0x78, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x40, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x03, dev.fx_dsp_addr);
+ outb (0x0f, dev.fx_dsp_msb);
+ outb (0xff, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x0b, dev.fx_dsp_addr);
+ outb (0x0f, dev.fx_dsp_msb);
+ outb (0xff, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x02, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x0a, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x46, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x49, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
/* Now, for some strange reason, lets reload every page
and all the coefficients over again. I have *NO* idea
@@ -3461,117 +3461,116 @@ wffx_init (struct wf_config *hw)
is this phase is omitted.
*/
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x00, hw->fx_dsp_page);
- outb (0x10, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x00, dev.fx_dsp_page);
+ outb (0x10, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_zero_v2); i += 2) {
- outb (page_zero_v2[i], hw->fx_dsp_msb);
- outb (page_zero_v2[i+1], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_zero_v2[i], dev.fx_dsp_msb);
+ outb (page_zero_v2[i+1], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x01, hw->fx_dsp_page);
- outb (0x10, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x01, dev.fx_dsp_page);
+ outb (0x10, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_one_v2); i += 2) {
- outb (page_one_v2[i], hw->fx_dsp_msb);
- outb (page_one_v2[i+1], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_one_v2[i], dev.fx_dsp_msb);
+ outb (page_one_v2[i+1], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- if (!wffx_idle(hw)) return (-1);
- if (!wffx_idle(hw)) return (-1);
+ if (!wffx_idle()) return (-1);
+ if (!wffx_idle()) return (-1);
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x02, hw->fx_dsp_page);
- outb (0x10, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x02, dev.fx_dsp_page);
+ outb (0x10, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_two_v2); i++) {
- outb (page_two_v2[i], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_two_v2[i], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x03, hw->fx_dsp_page);
- outb (0x10, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x03, dev.fx_dsp_page);
+ outb (0x10, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_three_v2); i++) {
- outb (page_three_v2[i], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_three_v2[i], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x04, hw->fx_dsp_page);
- outb (0x10, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x04, dev.fx_dsp_page);
+ outb (0x10, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_four_v2); i++) {
- outb (page_four_v2[i], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_four_v2[i], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x06, hw->fx_dsp_page);
+ outb (FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x06, dev.fx_dsp_page);
/* Page six v.2 is algorithmic */
for (i = 0x10; i <= 0x3e; i += 2) {
- outb (i, hw->fx_dsp_addr);
- outb (0x00, hw->fx_dsp_msb);
- outb (0x00, hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (i, dev.fx_dsp_addr);
+ outb (0x00, dev.fx_dsp_msb);
+ outb (0x00, dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (FX_AUTO_INCR|FX_LSB_TRANSFER, hw->fx_lcr);
- outb (0x07, hw->fx_dsp_page);
- outb (0x10, hw->fx_dsp_addr);
+ outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev.fx_lcr);
+ outb (0x07, dev.fx_dsp_page);
+ outb (0x10, dev.fx_dsp_addr);
for (i = 0; i < sizeof (page_seven_v2); i += 2) {
- outb (page_seven_v2[i], hw->fx_dsp_msb);
- outb (page_seven_v2[i+1], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (page_seven_v2[i], dev.fx_dsp_msb);
+ outb (page_seven_v2[i+1], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
for (i = 0x00; i < sizeof(mod_v2); i += 2) {
- outb (mod_v2[i], hw->fx_mod_addr);
- outb (mod_v2[i+1], hw->fx_mod_data);
- if (!wffx_idle(hw)) return (-1);
+ outb (mod_v2[i], dev.fx_mod_addr);
+ outb (mod_v2[i+1], dev.fx_mod_data);
+ if (!wffx_idle()) return (-1);
}
for (i = 0; i < sizeof (coefficients2); i += 4) {
- outb (coefficients2[i], hw->fx_dsp_page);
- outb (coefficients2[i+1], hw->fx_dsp_addr);
- outb (coefficients2[i+2], hw->fx_dsp_msb);
- outb (coefficients2[i+3], hw->fx_dsp_lsb);
- if (!wffx_idle(hw)) return (-1);
+ outb (coefficients2[i], dev.fx_dsp_page);
+ outb (coefficients2[i+1], dev.fx_dsp_addr);
+ outb (coefficients2[i+2], dev.fx_dsp_msb);
+ outb (coefficients2[i+3], dev.fx_dsp_lsb);
+ if (!wffx_idle()) return (-1);
}
- outb (0x00, hw->fx_op);
- if (!wffx_idle(hw)) return (-1);
-
for (i = 0; i < sizeof (coefficients3); i += 2) {
int x;
- outb (0x07, hw->fx_dsp_page);
+ outb (0x07, dev.fx_dsp_page);
x = (i % 4) ? 0x4e : 0x4c;
- outb (x, hw->fx_dsp_addr);
- outb (coefficients3[i], hw->fx_dsp_msb);
- outb (coefficients3[i+1], hw->fx_dsp_lsb);
+ outb (x, dev.fx_dsp_addr);
+ outb (coefficients3[i], dev.fx_dsp_msb);
+ outb (coefficients3[i+1], dev.fx_dsp_lsb);
}
- outb (0x00, hw->fx_op); /* mute off */
+ outb (0x00, dev.fx_op); /* mute off */
+ if (!wffx_idle()) return (-1);
return (0);
}
EXPORT_NO_SYMBOLS;
-struct address_info cfg;
int io = -1;
int irq = -1;
-MODULE_PARM(io,"i");
-MODULE_PARM(irq,"i");
+MODULE_AUTHOR ("Paul Barton-Davis <pbd@op.net>");
+MODULE_DESCRIPTION ("Turtle Beach WaveFront Linux Driver");
+MODULE_PARM (io,"i");
+MODULE_PARM (irq,"i");
int init_module (void)
@@ -3580,19 +3579,27 @@ int init_module (void)
"Copyright (C) by Hannu Solvainen, "
"Paul Barton-Davis 1993-1998.\n");
+ /* XXX t'would be lovely to ask the CS4232 for these values, eh ? */
+
if (io == -1 || irq == -1) {
- printk (KERN_INFO "WaveFront: irq and io "
- "options must be set.\n");
+ printk (KERN_INFO LOGNAME "irq and io options must be set.\n");
return -EINVAL;
}
- cfg.io_base = io;
- cfg.irq = irq;
+ if (wavefront_interrupt_bits (irq) < 0) {
+ printk (KERN_INFO LOGNAME
+ "IRQ must be 9, 5, 12 or 15 (not %d)\n", irq);
+ return -ENODEV;
+ }
- if (probe_wavefront (&cfg) == 0) {
+ if (detect_wavefront (irq, io) < 0) {
return -ENODEV;
}
- attach_wavefront (&cfg);
+
+ if (install_wavefront () < 0) {
+ return -EIO;
+ }
+
SOUND_LOCK;
return 0;
}
@@ -3600,10 +3607,11 @@ int init_module (void)
void cleanup_module (void)
{
- unload_wavefront (&cfg);
+ uninstall_wavefront ();
+
SOUND_LOCK_END;
}
-#endif CONFIG_SOUND_WAVEFRONT_MODULE_AND_MODULE
+#endif CONFIG_SOUND_WAVEFRONT_MODULE && MODULE
diff --git a/drivers/sound/wf_midi.c b/drivers/sound/wf_midi.c
index ee26fb1ec..a8c6fc829 100644
--- a/drivers/sound/wf_midi.c
+++ b/drivers/sound/wf_midi.c
@@ -40,7 +40,7 @@
/*
* Copyright (C) by Paul Barton-Davis 1998
- * Substantial portions of this file are derived from work that is:
+ * Some portions of this file are derived from work that is:
*
* Copyright (C) by Hannu Savolainen 1993-1996
*
@@ -50,17 +50,22 @@
*/
#include <linux/config.h>
+#include <linux/init.h>
#include "sound_config.h"
#include "soundmodule.h"
#include <linux/wavefront.h>
-#if (defined(CONFIG_WAVEFRONT) && defined(CONFIG_MIDI)) || defined(MODULE)
+#if defined(CONFIG_SOUND_WAVEFRONT_MODULE) && defined(MODULE)
struct wf_mpu_config {
- int base; /* I/O base */
+ int base;
+#define DATAPORT(d) (d)->base
+#define COMDPORT(d) (d)->base+1
+#define STATPORT(d) (d)->base+1
+
int irq;
- int opened; /* Open mode */
+ int opened;
int devno;
int synthno;
int mode;
@@ -68,69 +73,54 @@ struct wf_mpu_config {
#define MODE_SYNTH 2
void (*inputintr) (int dev, unsigned char data);
-
- /* Virtual MIDI support */
-
- char configured_for_virtual; /* setup for virtual completed */
char isvirtual; /* do virtual I/O stuff */
- char isexternal; /* i am an external interface */
- int internal; /* external interface midi_devno */
- int external; /* external interface midi_devno */
};
-#define DATAPORT(base) (base)
-#define COMDPORT(base) (base+1)
-#define STATPORT(base) (base+1)
+static struct wf_mpu_config devs[2];
+static struct wf_mpu_config *phys_dev = &devs[0];
+static struct wf_mpu_config *virt_dev = &devs[1];
-static void start_uart_mode (struct wf_mpu_config *devc);
+static void start_uart_mode (void);
-static int
-wf_mpu_status (struct wf_mpu_config *devc)
-{
- return inb (STATPORT (devc->base));
-}
+#define OUTPUT_READY 0x40
+#define INPUT_AVAIL 0x80
+#define MPU_ACK 0xFE
+#define UART_MODE_ON 0x3F
+
+static inline int
+wf_mpu_status (void)
-static void
-wf_mpu_cmd (struct wf_mpu_config *devc, unsigned char cmd)
{
- outb ((cmd), COMDPORT(devc->base));
+ return inb (STATPORT (phys_dev));
}
-#define input_avail(devc) (!(wf_mpu_status(devc)&INPUT_AVAIL))
-#define output_ready(devc) (!(wf_mpu_status(devc)&OUTPUT_READY))
+static inline int
+input_avail (void)
-static int
-read_data (struct wf_mpu_config *devc)
{
- return inb (DATAPORT (devc->base));
+ return !(wf_mpu_status() & INPUT_AVAIL);
}
-static void
-write_data (struct wf_mpu_config *devc, unsigned char byte)
+static inline int
+output_ready (void)
+
{
- outb (byte, DATAPORT (devc->base));
+ return !(wf_mpu_status() & OUTPUT_READY);
}
-#define OUTPUT_READY 0x40
-#define INPUT_AVAIL 0x80
-#define MPU_ACK 0xFE
-#define MPU_RESET 0xFF
-#define UART_MODE_ON 0x3F
+static inline int
+read_data (void)
-static struct wf_mpu_config dev_conf[MAX_MIDI_DEV] =
{
- {0}
-};
-
-static volatile int irq2dev[17] =
-{-1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ return inb (DATAPORT (phys_dev));
+}
-static struct synth_info wf_mpu_synth_info_proto =
-{"WaveFront MPU-401 interface", 0,
- SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};
+static inline void
+write_data (unsigned char byte)
-static struct synth_info wf_mpu_synth_info[MAX_MIDI_DEV];
+{
+ outb (byte, DATAPORT (phys_dev));
+}
/*
* States for the input scanner (should be in dev_table.h)
@@ -162,11 +152,10 @@ static unsigned char len_tab[] = /* # of data bytes following a status
};
static int
-wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
-{
- struct midi_input_info *mi;
+wf_mpu_input_scanner (int devno, int synthdev, unsigned char midic)
- mi = &midi_devs[devc->devno]->in_info;
+{
+ struct midi_input_info *mi = &midi_devs[devno]->in_info;
switch (mi->m_state) {
case MST_INIT:
@@ -236,8 +225,7 @@ wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
if (mi->m_left <= 0) {
mi->m_state = MST_INIT;
- do_midi_msg (devc->synthno, mi->m_buf,
- mi->m_ptr);
+ do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
mi->m_ptr = 0;
}
} else if (msg == 0xf) { /* MPU MARK */
@@ -266,8 +254,7 @@ wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
if (mi->m_left <= 0) {
mi->m_state = MST_INIT;
- do_midi_msg (devc->synthno, mi->m_buf,
- mi->m_ptr);
+ do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
mi->m_ptr = 0;
}
}
@@ -362,7 +349,7 @@ wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
mi->m_buf[mi->m_ptr++] = midic;
if ((--mi->m_left) <= 0) {
mi->m_state = MST_INIT;
- do_midi_msg (devc->synthno, mi->m_buf, mi->m_ptr);
+ do_midi_msg (synthdev, mi->m_buf, mi->m_ptr);
mi->m_ptr = 0;
}
break;
@@ -375,78 +362,65 @@ wf_mpu_input_scanner (struct wf_mpu_config *devc, unsigned char midic)
return 1;
}
-void wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
+void
+wf_mpuintr (int irq, void *dev_id, struct pt_regs *dummy)
+
{
- struct wf_mpu_config *devc;
- int dev;
- static struct wf_mpu_config *isrc = 0;
+ struct wf_mpu_config *physical_dev = dev_id;
+ static struct wf_mpu_config *input_dev = 0;
+ struct midi_input_info *mi = &midi_devs[physical_dev->devno]->in_info;
int n;
- struct midi_input_info *mi;
- if (irq < 0 || irq > 15)
- {
- printk (KERN_ERR "WF-MPU: bogus interrupt #%d", irq);
+ if (!input_avail()) { /* not for us */
return;
}
- dev = irq2dev[irq];
- mi = &midi_devs[dev]->in_info;
- if (mi->m_busy)
- return;
+
+ if (mi->m_busy) return;
mi->m_busy = 1;
-
sti ();
- n = 50;
-
- /* guarantee that we're working with the "real" (internal)
- interface before doing anything physical.
- */
+ if (!input_dev) {
+ input_dev = physical_dev;
+ }
- devc = &dev_conf[dev];
- devc = &dev_conf[devc->internal];
+ n = 50; /* XXX why ? */
- if (isrc == 0) {
-
- /* This is just an initial setting. If Virtual MIDI mode is
- enabled on the ICS2115, we'll get a switch char before
- anything else, and if it isn't, then the guess will be
- correct for our purposes.
- */
-
- isrc = &dev_conf[devc->internal];
- }
-
- while (input_avail (devc) && n-- > 0) {
- unsigned char c = read_data (devc);
+ do {
+ unsigned char c = read_data ();
- if (devc->isvirtual) {
+ if (phys_dev->isvirtual) {
+
if (c == WF_EXTERNAL_SWITCH) {
- isrc = &dev_conf[devc->external];
+ input_dev = virt_dev;
continue;
} else if (c == WF_INTERNAL_SWITCH) {
- isrc = &dev_conf[devc->internal];
+ input_dev = phys_dev;
continue;
} /* else just leave it as it is */
+
} else {
- isrc = &dev_conf[devc->internal];
+ input_dev = phys_dev;
}
- if (isrc->mode == MODE_SYNTH) {
+ if (input_dev->mode == MODE_SYNTH) {
- wf_mpu_input_scanner (isrc, c);
+ wf_mpu_input_scanner (input_dev->devno,
+ input_dev->synthno, c);
- } else if (isrc->opened & OPEN_READ) {
+ } else if (input_dev->opened & OPEN_READ) {
- if (isrc->inputintr) {
- isrc->inputintr (isrc->devno, c);
+ if (input_dev->inputintr) {
+ input_dev->inputintr (input_dev->devno, c);
}
}
- }
+
+ } while (input_avail() && n-- > 0);
mi->m_busy = 0;
}
-static int wf_mpu_open (int dev, int mode,
+static int
+wf_mpu_open (int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
)
@@ -456,7 +430,14 @@ static int wf_mpu_open (int dev, int mode,
if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
return -(ENXIO);
- devc = &dev_conf[dev];
+ if (phys_dev->devno == dev) {
+ devc = phys_dev;
+ } else if (phys_dev->isvirtual && virt_dev->devno == dev) {
+ devc = virt_dev;
+ } else {
+ printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
+ return -(EINVAL);
+ }
if (devc->opened) {
return -(EBUSY);
@@ -475,7 +456,18 @@ wf_mpu_close (int dev)
{
struct wf_mpu_config *devc;
- devc = &dev_conf[dev];
+ if (dev < 0 || dev >= num_midis || midi_devs[dev]==NULL)
+ return;
+
+ if (phys_dev->devno == dev) {
+ devc = phys_dev;
+ } else if (phys_dev->isvirtual && virt_dev->devno == dev) {
+ devc = virt_dev;
+ } else {
+ printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
+ return;
+ }
+
devc->mode = 0;
devc->inputintr = NULL;
devc->opened = 0;
@@ -487,40 +479,35 @@ wf_mpu_out (int dev, unsigned char midi_byte)
int timeout;
unsigned long flags;
static int lastoutdev = -1;
-
- struct wf_mpu_config *devc;
unsigned char switchch;
- /* The actual output has to occur using the "internal" config info
- */
-
- devc = &dev_conf[dev_conf[dev].internal];
-
- if (devc->isvirtual && lastoutdev != dev) {
+ if (phys_dev->isvirtual && lastoutdev != dev) {
- if (dev == devc->internal) {
+ if (dev == phys_dev->devno) {
switchch = WF_INTERNAL_SWITCH;
- } else if (dev == devc->external) {
+ } else if (dev == virt_dev->devno) {
switchch = WF_EXTERNAL_SWITCH;
} else {
printk (KERN_ERR "WF-MPU: bad device number %d", dev);
return (0);
}
+
+ /* XXX fix me */
- for (timeout = 30000; timeout > 0 && !output_ready (devc);
+ for (timeout = 30000; timeout > 0 && !output_ready ();
timeout--);
save_flags (flags);
cli ();
- if (!output_ready (devc)) {
+ if (!output_ready ()) {
printk (KERN_WARNING "WF-MPU: Send switch "
"byte timeout\n");
restore_flags (flags);
return 0;
}
- write_data (devc, switchch);
+ write_data (switchch);
restore_flags (flags);
}
@@ -531,17 +518,19 @@ wf_mpu_out (int dev, unsigned char midi_byte)
* (After reset). Normally it takes just about 10 loops.
*/
- for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--);
+ /* XXX fix me */
+
+ for (timeout = 30000; timeout > 0 && !output_ready (); timeout--);
save_flags (flags);
cli ();
- if (!output_ready (devc)) {
+ if (!output_ready ()) {
printk (KERN_WARNING "WF-MPU: Send data timeout\n");
restore_flags (flags);
return 0;
}
- write_data (devc, midi_byte);
+ write_data (midi_byte);
restore_flags (flags);
return 1;
@@ -567,35 +556,63 @@ wf_mpu_ioctl (int dev, unsigned cmd, caddr_t arg)
return -(EINVAL);
}
-static void
-wf_mpu_kick (int dev)
-{
-}
-
static int
wf_mpu_buffer_status (int dev)
{
- return 0; /*
- * No data in buffers
- */
+ return 0;
}
+static struct synth_operations wf_mpu_synth_operations[2];
+static struct midi_operations wf_mpu_midi_operations[2];
+
+static struct midi_operations wf_mpu_midi_proto =
+{
+ {"WF-MPU MIDI", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
+ NULL, /*converter*/
+ {0}, /* in_info */
+ wf_mpu_open,
+ wf_mpu_close,
+ wf_mpu_ioctl,
+ wf_mpu_out,
+ wf_mpu_start_read,
+ wf_mpu_end_read,
+ NULL,
+ NULL,
+ wf_mpu_buffer_status,
+ NULL
+};
+
+static struct synth_info wf_mpu_synth_info_proto =
+{"WaveFront MPU-401 interface", 0,
+ SYNTH_TYPE_MIDI, MIDI_TYPE_MPU401, 0, 128, 0, 128, SYNTH_CAP_INPUT};
+
+static struct synth_info wf_mpu_synth_info[2];
+
static int
wf_mpu_synth_ioctl (int dev,
unsigned int cmd, caddr_t arg)
{
int midi_dev;
+ int index;
midi_dev = synth_devs[dev]->midi_dev;
if (midi_dev < 0 || midi_dev > num_midis || midi_devs[midi_dev]==NULL)
return -(ENXIO);
+ if (midi_dev == phys_dev->devno) {
+ index = 0;
+ } else if (phys_dev->isvirtual && midi_dev == virt_dev->devno) {
+ index = 1;
+ } else {
+ return -(EINVAL);
+ }
+
switch (cmd) {
case SNDCTL_SYNTH_INFO:
copy_to_user (&((char *) arg)[0],
- &wf_mpu_synth_info[midi_dev],
+ &wf_mpu_synth_info[index],
sizeof (struct synth_info));
return 0;
@@ -622,7 +639,15 @@ wf_mpu_synth_open (int dev, int mode)
return -(ENXIO);
}
- devc = &dev_conf[midi_dev];
+ if (phys_dev->devno == midi_dev) {
+ devc = phys_dev;
+ } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) {
+ devc = virt_dev;
+ } else {
+ printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
+ return -(EINVAL);
+ }
+
if (devc->opened) {
return -(EBUSY);
}
@@ -642,12 +667,21 @@ wf_mpu_synth_close (int dev)
midi_dev = synth_devs[dev]->midi_dev;
- devc = &dev_conf[midi_dev];
+ if (phys_dev->devno == midi_dev) {
+ devc = phys_dev;
+ } else if (phys_dev->isvirtual && virt_dev->devno == midi_dev) {
+ devc = virt_dev;
+ } else {
+ printk (KERN_ERR "WF-MPU: unknown device number %d\n", dev);
+ return;
+ }
+
devc->inputintr = NULL;
devc->opened = 0;
devc->mode = 0;
}
+#define _MIDI_SYNTH_C_
#define MIDI_SYNTH_NAME "WaveFront (MIDI)"
#define MIDI_SYNTH_CAPS SYNTH_CAP_INPUT
#include "midi_synth.h"
@@ -678,233 +712,145 @@ static struct synth_operations wf_mpu_synth_proto =
midi_synth_send_sysex
};
-static struct synth_operations wf_mpu_synth_operations[2];
-static struct midi_operations wf_mpu_midi_operations[2];
-static int wfmpu_cnt = 0;
-
-static struct midi_operations wf_mpu_midi_proto =
-{
- {"WF-MPU MIDI", 0, MIDI_CAP_MPU401, SNDCARD_MPU401},
- NULL, /*converter*/
- {0}, /* in_info */
- wf_mpu_open,
- wf_mpu_close,
- wf_mpu_ioctl,
- wf_mpu_out,
- wf_mpu_start_read,
- wf_mpu_end_read,
- wf_mpu_kick,
- NULL,
- wf_mpu_buffer_status,
- NULL
-};
-
-
static int
-config_wf_mpu (int dev, struct address_info *hw_config)
+config_wf_mpu (struct wf_mpu_config *dev)
{
- struct wf_mpu_config *devc;
- int internal;
-
- if (wfmpu_cnt >= 2) {
- printk (KERN_ERR "WF-MPU: more MPU devices than cards ?!!\n");
- return (-1);
- }
-
- /* There is no synth available on the external interface,
- so do the synth stuff to the internal interface only.
- */
-
- internal = dev_conf[dev].internal;
- devc = &dev_conf[internal];
-
- if (!dev_conf[dev].isexternal) {
- memcpy ((char *) &wf_mpu_synth_operations[wfmpu_cnt],
+ int is_external;
+ char *name;
+ int index;
+
+ if (dev == phys_dev) {
+ name = "WaveFront internal MIDI";
+ is_external = 0;
+ index = 0;
+ memcpy ((char *) &wf_mpu_synth_operations[index],
(char *) &wf_mpu_synth_proto,
sizeof (struct synth_operations));
- }
-
- memcpy ((char *) &wf_mpu_midi_operations[wfmpu_cnt],
- (char *) &wf_mpu_midi_proto,
- sizeof (struct midi_operations));
-
- if (dev_conf[dev].isexternal) {
- wf_mpu_midi_operations[wfmpu_cnt].converter = NULL;
} else {
- wf_mpu_midi_operations[wfmpu_cnt].converter =
- &wf_mpu_synth_operations[wfmpu_cnt];
+ name = "WaveFront external MIDI";
+ is_external = 1;
+ index = 1;
+ /* no synth operations for an external MIDI interface */
}
- memcpy ((char *) &wf_mpu_synth_info[dev],
+ memcpy ((char *) &wf_mpu_synth_info[dev->devno],
(char *) &wf_mpu_synth_info_proto,
sizeof (struct synth_info));
- strcpy (wf_mpu_synth_info[dev].name, hw_config->name);
- strcpy (wf_mpu_midi_operations[wfmpu_cnt].info.name, hw_config->name);
+ strcpy (wf_mpu_synth_info[index].name, name);
- conf_printf (hw_config->name, hw_config);
+ wf_mpu_synth_operations[index].midi_dev = dev->devno;
+ wf_mpu_synth_operations[index].info = &wf_mpu_synth_info[index];
- if (!dev_conf[dev].isexternal) {
- wf_mpu_synth_operations[wfmpu_cnt].midi_dev = dev;
+ memcpy ((char *) &wf_mpu_midi_operations[index],
+ (char *) &wf_mpu_midi_proto,
+ sizeof (struct midi_operations));
+
+ if (is_external) {
+ wf_mpu_midi_operations[index].converter = NULL;
+ } else {
+ wf_mpu_midi_operations[index].converter =
+ &wf_mpu_synth_operations[index];
}
- wf_mpu_synth_operations[wfmpu_cnt].info = &wf_mpu_synth_info[dev];
-
- midi_devs[dev] = &wf_mpu_midi_operations[wfmpu_cnt];
- dev_conf[dev].opened = 0;
- dev_conf[dev].mode = 0;
- dev_conf[dev].configured_for_virtual = 0;
- dev_conf[dev].devno = dev;
+ strcpy (wf_mpu_midi_operations[index].info.name, name);
- midi_devs[dev]->in_info.m_busy = 0;
- midi_devs[dev]->in_info.m_state = MST_INIT;
- midi_devs[dev]->in_info.m_ptr = 0;
- midi_devs[dev]->in_info.m_left = 0;
- midi_devs[dev]->in_info.m_prev_status = 0;
+ midi_devs[dev->devno] = &wf_mpu_midi_operations[index];
+ midi_devs[dev->devno]->in_info.m_busy = 0;
+ midi_devs[dev->devno]->in_info.m_state = MST_INIT;
+ midi_devs[dev->devno]->in_info.m_ptr = 0;
+ midi_devs[dev->devno]->in_info.m_left = 0;
+ midi_devs[dev->devno]->in_info.m_prev_status = 0;
- wfmpu_cnt++;
+ devs[index].opened = 0;
+ devs[index].mode = 0;
return (0);
}
-int
-virtual_midi_enable (int dev, struct address_info *hw_config)
+int virtual_midi_enable (void)
{
- int idev;
- int edev;
- struct wf_mpu_config *devc;
-
- devc = &dev_conf[dev];
-
- if (devc->configured_for_virtual) {
-
- idev = devc->internal;
- edev = devc->external;
-
- } else {
-
- if (hw_config == NULL) {
- printk (KERN_ERR
- "WF-MPU: virtual midi first "
- "enabled without hw_config!\n");
- return -EINVAL;
- }
+ if ((virt_dev->devno < 0) &&
+ (virt_dev->devno = sound_alloc_mididev()) == -1) {
+ printk (KERN_ERR
+ "WF-MPU: too many midi devices detected\n");
+ return -1;
+ }
- idev = devc->internal;
+ config_wf_mpu (virt_dev);
- if ((edev = sound_alloc_mididev()) == -1) {
- printk (KERN_ERR
- "WF-MPU: too many midi devices detected\n");
- return -1;
- }
+ phys_dev->isvirtual = 1;
+ return virt_dev->devno;
+}
- hw_config->slots[WF_EXTERNAL_MIDI_SLOT] = edev;
- }
+int
+virtual_midi_disable (void)
- dev_conf[edev].isvirtual = 1;
- dev_conf[idev].isvirtual = 1;
-
- if (dev_conf[idev].configured_for_virtual) {
- return 0;
- }
+{
+ unsigned long flags;
- /* Configure external interface struct */
+ save_flags (flags);
+ cli();
- devc = &dev_conf[edev];
- devc->internal = idev;
- devc->external = edev;
- devc->isexternal = 1;
+ wf_mpu_close (virt_dev->devno);
+ /* no synth on virt_dev, so no need to call wf_mpu_synth_close() */
+ phys_dev->isvirtual = 0;
- /* Configure external interface struct
- (devc->isexternal and devc->internal set in attach_wf_mpu())
- */
+ restore_flags (flags);
- devc = &dev_conf[idev];
- devc->external = edev;
+ return 0;
+}
- /* Configure the tables for the external */
+__initfunc (static int detect_wf_mpu (int irq, int io_base))
- if (config_wf_mpu (edev, hw_config)) {
- printk (KERN_WARNING "WF-MPU: configuration for MIDI "
- "device %d failed\n", edev);
- return (-1);
+{
+ if (check_region (io_base, 2)) {
+ printk (KERN_WARNING "WF-MPU: I/O port %x already in use.\n",
+ io_base);
+ return -1;
}
- /* Don't bother to do this again if we are toggled back and
- forth between virtual MIDI mode and "normal" operation.
- */
-
- dev_conf[edev].configured_for_virtual = 1;
- dev_conf[idev].configured_for_virtual = 1;
+ phys_dev->base = io_base;
+ phys_dev->irq = irq;
+ phys_dev->devno = -1;
+ virt_dev->devno = -1;
return 0;
}
-void
-virtual_midi_disable (int dev)
+__initfunc (int install_wf_mpu (void))
{
- struct wf_mpu_config *devc;
- unsigned long flags;
+ if ((phys_dev->devno = sound_alloc_mididev()) < 0){
- save_flags (flags);
- cli();
-
- /* Assumes for logical purposes that the caller has taken
- care of fiddling with WaveFront hardware commands to
- turn off Virtual MIDI mode.
- */
-
- devc = &dev_conf[dev];
+ printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
+ return -1;
- devc = &dev_conf[devc->internal];
- devc->isvirtual = 0;
+ }
- devc = &dev_conf[devc->external];
- devc->isvirtual = 0;
+ request_region (phys_dev->base, 2, "wavefront midi");
+ phys_dev->isvirtual = 0;
- restore_flags (flags);
-}
+ if (config_wf_mpu (phys_dev)) {
-void
-attach_wf_mpu (struct address_info *hw_config)
-{
- int m;
- struct wf_mpu_config *devc;
-
- if (request_irq (hw_config->irq, wf_mpuintr,
- 0, "WaveFront MIDI", NULL) < 0) {
- printk (KERN_ERR "WF-MPU: Failed to allocate IRQ%d\n",
- hw_config->irq);
- return;
- }
+ printk (KERN_WARNING
+ "WF-MPU: configuration for MIDI device %d failed\n",
+ phys_dev->devno);
+ sound_unload_mididev (phys_dev->devno);
- if ((m = sound_alloc_mididev()) == -1){
- printk (KERN_ERR "WF-MPU: Too many MIDI devices detected.\n");
- free_irq (hw_config->irq, NULL);
- release_region (hw_config->io_base, 2);
- return;
}
- request_region (hw_config->io_base, 2, "WaveFront MPU");
+ /* OK, now we're configured to handle an interrupt ... */
- hw_config->slots[WF_INTERNAL_MIDI_SLOT] = m;
- devc = &dev_conf[m];
- devc->base = hw_config->io_base;
- devc->irq = hw_config->irq;
- devc->isexternal = 0;
- devc->internal = m;
- devc->external = -1;
- devc->isvirtual = 0;
+ if (request_irq (phys_dev->irq, wf_mpuintr, SA_INTERRUPT|SA_SHIRQ,
+ "wavefront midi", phys_dev) < 0) {
- irq2dev[devc->irq] = m;
+ printk (KERN_ERR "WF-MPU: Failed to allocate IRQ%d\n",
+ phys_dev->irq);
+ return -1;
- if (config_wf_mpu (m, hw_config)) {
- printk (KERN_WARNING
- "WF-MPU: configuration for MIDI device %d failed\n", m);
- sound_unload_mididev (m);
}
/* This being a WaveFront (ICS-2115) emulated MPU-401, we have
@@ -912,64 +858,43 @@ attach_wf_mpu (struct address_info *hw_config)
won't do anything at all.
*/
- start_uart_mode (devc);
+ start_uart_mode ();
+ return phys_dev->devno;
}
-
-int
-probe_wf_mpu (struct address_info *hw_config)
-
-{
- if (hw_config->irq < 0 || hw_config->irq > 16) {
- printk (KERN_WARNING "WF-MPU: bogus IRQ value requested (%d)\n",
- hw_config->irq);
- return 0;
- }
-
- if (check_region (hw_config->io_base, 2)) {
- printk (KERN_WARNING "WF-MPU: I/O port %x already in use\n\n",
- hw_config->io_base);
- return 0;
- }
-
- if (inb (hw_config->io_base + 1) == 0xff) { /* Just bus float? */
- printk ("WF-MPU: Port %x looks dead.\n", hw_config->io_base);
- return 0;
- }
-
- return 1;
-}
-
+
void
-unload_wf_mpu (struct address_info *hw_config)
+uninstall_wf_mpu (void)
+
{
+ release_region (phys_dev->base, 2);
+ free_irq (phys_dev->irq, phys_dev);
+ sound_unload_mididev (phys_dev->devno);
- release_region (hw_config->io_base, 2);
- sound_unload_mididev (hw_config->slots[WF_INTERNAL_MIDI_SLOT]);
- if (hw_config->irq > 0) {
- free_irq (hw_config->irq, NULL);
- }
- if (hw_config->slots[WF_EXTERNAL_MIDI_SLOT] > 0) {
- sound_unload_mididev (hw_config->slots[WF_EXTERNAL_MIDI_SLOT]);
+ if (virt_dev->devno >= 0) {
+ sound_unload_mididev (virt_dev->devno);
}
}
static void
-start_uart_mode (struct wf_mpu_config *devc)
+start_uart_mode (void)
+
{
- int ok, timeout;
+ int ok, i;
unsigned long flags;
save_flags (flags);
cli ();
- for (timeout = 30000; timeout > 0 && !output_ready (devc); timeout--);
+ /* XXX fix me */
- wf_mpu_cmd (devc, UART_MODE_ON);
+ for (i = 0; i < 30000 && !output_ready (); i++);
- for (ok = 0, timeout = 50000; timeout > 0 && !ok; timeout--) {
- if (input_avail (devc)) {
- if (read_data (devc) == MPU_ACK) {
+ outb (UART_MODE_ON, COMDPORT(phys_dev));
+
+ for (ok = 0, i = 50000; i > 0 && !ok; i--) {
+ if (input_avail ()) {
+ if (read_data () == MPU_ACK) {
ok = 1;
}
}
@@ -978,6 +903,30 @@ start_uart_mode (struct wf_mpu_config *devc)
restore_flags (flags);
}
-#endif
+#ifdef OSS_SUPPORT
+
+int
+probe_wf_mpu (struct address_info *hw_config)
+
+{
+ return !detect_wf_mpu (hw_config->irq, hw_config->io_base);
+}
+
+void
+attach_wf_mpu (struct address_info *hw_config)
+
+{
+ (void) install_wf_mpu ();
+}
+
+void
+unload_wf_mpu (void)
+{
+ uninstall_wf_mpu ();
+}
+
+#endif OSS_SUPPORT
+
+#endif CONFIG_SOUND_WAVEFRONT_MODULE_AND_MODULE
diff --git a/drivers/video/Config.in b/drivers/video/Config.in
index 7c1887c1c..7224b174f 100644
--- a/drivers/video/Config.in
+++ b/drivers/video/Config.in
@@ -4,6 +4,15 @@
if [ "$CONFIG_FB" = "y" ]; then
define_bool CONFIG_DUMMY_CONSOLE y
+ if [ "$CONFIG_APUS" = "y" ]; then
+ bool 'Permedia2 support' CONFIG_FB_PM2
+ if [ "$CONFIG_FB_PM2" = "y" ]; then
+ bool ' enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
+ if [ "$CONFIG_APUS" = "y" ]; then
+ bool ' Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC
+ fi
+ fi
+ fi
if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
bool 'Acorn VIDC support' CONFIG_FB_ACORN
fi
@@ -22,7 +31,6 @@ if [ "$CONFIG_FB" = "y" ]; then
tristate 'Amiga CyberVision support' CONFIG_FB_CYBER
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE
- bool 'Amiga CyberVisionPPC support (experimental)' CONFIG_FB_CVPPC
tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN
fi
@@ -157,7 +165,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
- "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" ]; then
+ "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
+ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then ]; then
define_bool CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -169,7 +178,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" ]; then
+ "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
+ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
define_bool CONFIG_FBCON_CFB8 m
fi
fi
@@ -179,7 +189,8 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
"$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
- "$CONFIG_FB_MATROX" = "y" ]; then
+ "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
+ "$CONFIG_FB_PM2" = "y" ]; then
define_bool CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -188,18 +199,19 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
"$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- "$CONFIG_FB_MATROX" = "m" ]; then
+ "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
+ "$CONFIG_FB_PM2" = "m" ]; then
define_bool CONFIG_FBCON_CFB16 m
fi
fi
if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
"$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
- "$CONFIG_FB_MATROX" = "y" ]; then
+ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
define_bool CONFIG_FBCON_CFB24 y
else
if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
- "$CONFIG_FB_MATROX" = "m" ]; then
+ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
define_bool CONFIG_FBCON_CFB24 m
fi
fi
@@ -207,14 +219,14 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
- "$CONFIG_FB_MATROX" = "y" ]; then
+ "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
define_bool CONFIG_FBCON_CFB32 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- "$CONFIG_FB_MATROX" = "m" ]; then
+ "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
define_bool CONFIG_FBCON_CFB32 m
fi
fi
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 5343be151..5c049664a 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -79,6 +79,11 @@ else
endif
endif
+ifeq ($(CONFIG_FB_PM2),y)
+L_OBJS += pm2fb.o
+CONFIG_FBGEN_BUILTIN = y
+endif
+
ifeq ($(CONFIG_FB_APOLLO),y)
L_OBJS += dnfb.o
endif
@@ -123,11 +128,6 @@ else
endif
endif
-ifeq ($(CONFIG_FB_CVPPC),y)
-L_OBJS += cvppcfb.o
-CONFIG_FBGEN_BUILTIN = y
-endif
-
ifeq ($(CONFIG_FB_MAC),y)
L_OBJS += macfb.o
endif
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index ed588ab0d..2aa4a29e3 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -623,6 +623,7 @@ static u_short maxfmode, chipset;
static u_long videomemory, spritememory;
static u_long videomemorysize;
+static u_long videomemory_phys;
/*
* This is the earliest allowed start of fetching display data.
@@ -1479,8 +1480,7 @@ static int amifb_set_var(struct fb_var_screeninfo *var, int con,
struct fb_fix_screeninfo fix;
ami_encode_fix(&fix, &par);
- display->screen_base =
- phys_to_virt ((unsigned long) fix.smem_start);
+ display->screen_base = (char *)videomemory;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -1877,6 +1877,18 @@ default_chipset:
assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
+ /*
+ * access the videomem with writethrough cache
+ */
+ videomemory_phys = (u_long)ZTWO_PADDR(videomemory);
+#if 1
+ videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
+#endif
+ if (!videomemory) {
+ printk("amifb: WARNING! unable to map videomem cached writethrough\n");
+ videomemory = ZTWO_VADDR(videomemory_phys);
+ }
+
memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
/*
@@ -2126,7 +2138,7 @@ static int ami_encode_fix(struct fb_fix_screeninfo *fix,
{
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, amifb_name);
- fix->smem_start = (char*) virt_to_phys((void *)videomemory);
+ fix->smem_start = (char *)videomemory_phys;
fix->smem_len = videomemorysize;
#ifdef FBCON_HAS_MFB
@@ -2742,16 +2754,16 @@ static int ami_update_par(void)
par->bpl1mod = par->bpl2mod;
if (par->yoffset) {
- par->bplpt0 = ZTWO_PADDR((u_long)videomemory + par->next_line*par->yoffset + move);
+ par->bplpt0 = videomemory_phys + par->next_line*par->yoffset + move;
if (par->vmode & FB_VMODE_YWRAP) {
if (par->yoffset > par->vyres-par->yres) {
- par->bplpt0wrap = ZTWO_PADDR((u_long)videomemory + move);
+ par->bplpt0wrap = videomemory_phys + move;
if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
par->bplpt0wrap += par->next_line;
}
}
} else
- par->bplpt0 = ZTWO_PADDR((u_long)videomemory + move);
+ par->bplpt0 = videomemory_phys + move;
if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
par->bplpt0 += par->next_line;
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 68c2a6fb2..f33d118b7 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -62,6 +62,7 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/irq.h>
+#include <asm/io.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
@@ -669,7 +670,7 @@ static void tt_get_par( struct atafb_par *par )
addr = ((shifter.bas_hi & 0xff) << 16) |
((shifter.bas_md & 0xff) << 8) |
((shifter.bas_lo & 0xff));
- par->screen_base = PTOV(addr);
+ par->screen_base = phys_to_virt(addr);
}
static void tt_set_par( struct atafb_par *par )
@@ -1502,7 +1503,7 @@ static void falcon_get_par( struct atafb_par *par )
addr = (shifter.bas_hi & 0xff) << 16 |
(shifter.bas_md & 0xff) << 8 |
(shifter.bas_lo & 0xff);
- par->screen_base = PTOV(addr);
+ par->screen_base = phys_to_virt(addr);
/* derived parameters */
hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
@@ -1929,7 +1930,7 @@ static void stste_get_par( struct atafb_par *par )
((shifter.bas_md & 0xff) << 8);
if (ATARIHW_PRESENT(EXTD_SHIFTER))
addr |= (shifter.bas_lo & 0xff);
- par->screen_base = PTOV(addr);
+ par->screen_base = phys_to_virt(addr);
}
static void stste_set_par( struct atafb_par *par )
@@ -2026,7 +2027,7 @@ static int stste_detect( void )
static void stste_set_screen_base(unsigned long s_base)
{
unsigned long addr;
- addr= VTOP(s_base);
+ addr= virt_to_phys(s_base);
/* Setup Screen Memory */
shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
@@ -2297,7 +2298,7 @@ static int ext_detect( void )
static void set_screen_base(unsigned long s_base)
{
unsigned long addr;
- addr= VTOP(s_base);
+ addr= virt_to_phys(s_base);
/* Setup Screen Memory */
shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
@@ -2819,9 +2820,9 @@ __initfunc(void atafb_init(void))
if (CPU_IS_040_OR_060) {
/* On a '040+, the cache mode of video RAM must be set to
* write-through also for internal video hardware! */
- cache_push( VTOP(screen_base), screen_len );
+ cache_push( virt_to_phys(screen_base), screen_len );
kernel_set_cachemode( screen_base, screen_len,
- KERNELMAP_NO_COPYBACK );
+ IOMAP_WRITETHROUGH );
}
#ifdef ATAFB_EXT
}
@@ -2829,11 +2830,9 @@ __initfunc(void atafb_init(void))
/* Map the video memory (physical address given) to somewhere
* in the kernel address space.
*/
- external_addr = kernel_map(external_addr, external_len,
- KERNELMAP_NO_COPYBACK, NULL);
+ external_addr = ioremap_writethrough(external_addr, external_len);
if (external_vgaiobase)
- external_vgaiobase = kernel_map(external_vgaiobase,
- 0x10000, KERNELMAP_NOCACHE_SER, NULL);
+ external_vgaiobase = ioremap(external_vgaiobase, 0x10000 );
screen_base =
real_screen_base = external_addr;
screen_len = external_len & PAGE_MASK;
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index e3f1b1d8d..6a3625d23 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.90 1998/11/20 12:27:03 geert Exp $
+/* $Id: atyfb.c,v 1.98 1999/01/14 08:50:53 geert Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -222,6 +222,7 @@ struct fb_info_aty {
u32 cfb32[16];
#endif
} fbcon_cmap;
+ u8 blitter_may_be_busy;
#ifdef __sparc__
u8 open;
u8 mmaped;
@@ -320,8 +321,7 @@ static char *strtoke(char *s, const char *ct);
#endif
static void reset_engine(const struct fb_info_aty *info);
-static void init_engine(const struct atyfb_par *par,
- const struct fb_info_aty *info);
+static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
#if defined(__sparc__) || defined(DEBUG)
@@ -533,10 +533,11 @@ static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info)
((u32)(0x8000 >> entries)));
}
-static inline void wait_for_idle(const struct fb_info_aty *info)
+static inline void wait_for_idle(struct fb_info_aty *info)
{
wait_for_fifo(16, info);
while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
+ info->blitter_may_be_busy = 0;
}
static void reset_engine(const struct fb_info_aty *info)
@@ -553,8 +554,7 @@ static void reset_engine(const struct fb_info_aty *info)
BUS_FIFO_ERR_ACK, info);
}
-static void init_engine(const struct atyfb_par *par,
- const struct fb_info_aty *info)
+static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
{
u32 pitch_value;
@@ -872,7 +872,8 @@ aty_set_cursor(struct fb_info_aty *fb, int on)
aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
fb);
}
- wait_for_idle(fb);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
}
static void
@@ -1457,7 +1458,7 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per)
vco_div_count = pll->m & 0x3f;
ref_div_count = pll->n;
- *vclk_per = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
+ *vclk_per = ((ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
return 0;
}
@@ -1608,6 +1609,7 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
return err;
if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
+ (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
(Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
(Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
(Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
@@ -1703,6 +1705,8 @@ static void atyfb_set_par(const struct atyfb_par *par,
info->current_par = *par;
+ if (info->blitter_may_be_busy)
+ wait_for_idle(info);
aty_set_crtc(info, &par->crtc);
aty_st_8(CLOCK_CNTL, 0, info);
aty_st_8(CLOCK_CNTL, CLOCK_STROBE, info);
@@ -1717,8 +1721,24 @@ static void atyfb_set_par(const struct atyfb_par *par,
break;
}
aty_set_pll_gx(info, &par->pll.gx);
- aty_st_le32(BUS_CNTL, 0x890e20f1, info);
- aty_st_le32(DAC_CNTL, 0x47052100, info);
+ aty_st_le32(BUS_CNTL, 0x590e10ff, info);
+ aty_st_le32(DAC_CNTL, 0x47012100, info);
+
+ /* Don't forget MEM_CNTL */
+ i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
+ switch (par->crtc.bpp) {
+ case 8:
+ i |= 0x02000000;
+ break;
+ case 16:
+ i |= 0x03000000;
+ break;
+ case 32:
+ i |= 0x06000000;
+ break;
+ }
+ aty_st_le32(MEM_CNTL, i, info);
+
} else {
aty_set_pll_ct(info, &par->pll.ct);
i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff;
@@ -2456,9 +2476,13 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
(Rev == 0x48))) ||
((Gx == VT_CHIP_ID) && ((Rev == 0x01) ||
(Rev == 0x9a))) ||
- (Gx == VU_CHIP_ID)) {
+ Gx == VU_CHIP_ID) {
/* VTA4 or VTB */
pll = 200;
+ } else if (Gx == VV_CHIP_ID) {
+ /* VT4 */
+ pll = 230;
+ mclk = 83;
} else if (Gx == VT_CHIP_ID) {
/* other VT */
pll = 135;
@@ -2470,15 +2494,19 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
(Gx == GU_CHIP_ID)) {
/* RAGE II+ */
pll = 200;
+ } else if (Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
+ Gx == GZ_CHIP_ID) {
+ /* RAGE IIC */
+ pll = 230;
+ mclk = 83;
} else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
- Gx == GQ_CHIP_ID || Gx == VV_CHIP_ID ||
- Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
- Gx == GZ_CHIP_ID || Gx == LD_CHIP_ID ||
- Gx == LG_CHIP_ID || Gx == LB_CHIP_ID ||
+ Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
+ Gx == LD_CHIP_ID || Gx == LG_CHIP_ID ||
Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
- /* RAGE PRO or IIC */
+ /* RAGE PRO or LT PRO */
pll = 230;
+ mclk = 100;
} else {
/* other RAGE */
pll = 135;
@@ -2736,6 +2764,7 @@ __initfunc(void atyfb_init(void))
addr = pdev->base_address[1];
if (!addr)
continue;
+ addr &= PCI_BASE_ADDRESS_MEM_MASK;
#ifdef __sparc__
/*
@@ -3006,12 +3035,9 @@ __initfunc(void atyfb_init(void))
* Map the video memory (physical address given) to somewhere in the
* kernel address space.
*/
- info->frame_buffer = kernel_map(phys_vmembase[m64_num],
- phys_size[m64_num],
- KERNELMAP_NOCACHE_SER, NULL);
+ info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
info->frame_buffer_phys = info->frame_buffer;
- info->ati_regbase = kernel_map(phys_guiregbase[m64_num], 0x10000,
- KERNELMAP_NOCACHE_SER, NULL)+0xFC00ul;
+ info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
info->ati_regbase_phys = info->ati_regbase;
if (!aty_init(info, "ISA bus")) {
@@ -3399,6 +3425,7 @@ static inline void draw_rect(s16 x, s16 y, u16 width, u16 height,
wait_for_fifo(2, info);
aty_st_le32(DST_Y_X, (x << 16) | y, info);
aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info);
+ info->blitter_may_be_busy = 1;
}
static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
@@ -3561,14 +3588,15 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb8_putc(conp, p, c, yy, xx);
}
@@ -3576,20 +3604,36 @@ static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
}
+static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+ if (fb->mmaped && currcon == fb->vtconsole)
+ return;
+#endif
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
+ fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
static struct display_switch fbcon_aty8 = {
fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc,
- fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+ fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_aty8_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
@@ -3598,14 +3642,15 @@ static struct display_switch fbcon_aty8 = {
static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb16_putc(conp, p, c, yy, xx);
}
@@ -3613,20 +3658,36 @@ static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
}
+static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+ if (fb->mmaped && currcon == fb->vtconsole)
+ return;
+#endif
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
+ fbcon_cfb16_clear_margins(conp, p, bottom_only);
+}
+
static struct display_switch fbcon_aty16 = {
fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc,
- fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+ fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_aty16_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
@@ -3635,14 +3696,15 @@ static struct display_switch fbcon_aty16 = {
static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb24_putc(conp, p, c, yy, xx);
}
@@ -3650,20 +3712,36 @@ static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
}
+static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+ if (fb->mmaped && currcon == fb->vtconsole)
+ return;
+#endif
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
+ fbcon_cfb24_clear_margins(conp, p, bottom_only);
+}
+
static struct display_switch fbcon_aty24 = {
- fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_aty24_putc,
- fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+ fbcon_cfb24_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty24_putc,
+ fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_aty24_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
@@ -3672,14 +3750,15 @@ static struct display_switch fbcon_aty24 = {
static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb32_putc(conp, p, c, yy, xx);
}
@@ -3687,20 +3766,36 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
-#ifdef __sparc__
struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+#ifdef __sparc__
if (fb->mmaped && currcon == fb->vtconsole)
return;
#endif
- wait_for_idle((struct fb_info_aty *)p->fb_info);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
}
+static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
+ int bottom_only)
+{
+ struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+ if (fb->mmaped && currcon == fb->vtconsole)
+ return;
+#endif
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle((struct fb_info_aty *)p->fb_info);
+ fbcon_cfb32_clear_margins(conp, p, bottom_only);
+}
+
static struct display_switch fbcon_aty32 = {
fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc,
- fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+ fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c
index 4e0bc74ed..2891b4877 100644
--- a/drivers/video/cgsixfb.c
+++ b/drivers/video/cgsixfb.c
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.11 1998/09/04 15:43:42 jj Exp $
+/* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $
* cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -534,6 +534,7 @@ static void cg6_reset (struct fb_info_sbusfb *fb)
unsigned int rev, conf;
struct cg6_tec *tec = fb->s.cg6.tec;
struct cg6_fbc *fbc = fb->s.cg6.fbc;
+ u32 mode;
/* Turn off stuff in the Transform Engine. */
tec->tec_matrix = 0;
@@ -552,15 +553,20 @@ static void cg6_reset (struct fb_info_sbusfb *fb)
*(fb->s.cg6.fhc) = conf;
}
- /* Set things in the FBC. */
- fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
+ /* Set things in the FBC. Bad things appear to happen if we do
+ * back to back store/loads on the mode register, so copy it
+ * out instead. */
+ mode = fbc->mode;
+ mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
CG6_FBC_BDISP_MASK);
- fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
+ mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
CG6_FBC_BDISP_0);
+ fbc->mode = mode;
+
fbc->clip = 0;
fbc->offx = 0;
fbc->offy = 0;
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 699ae96ff..eb5d8931c 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -53,11 +53,14 @@ struct fb_info_chips {
struct {
__u8 red, green, blue;
} palette[256];
+ unsigned long frame_buffer_phys;
__u8 *frame_buffer;
- __u8 *blitter_regs;
+ unsigned long blitter_regs_phys;
+ __u32 *blitter_regs;
+ unsigned long blitter_data_phys;
+ __u8 *blitter_data;
+ unsigned long io_base_phys;
__u8 *io_base;
- unsigned long chips_base_phys;
- unsigned long chips_io_phys;
struct fb_info_chips *next;
#ifdef CONFIG_PMAC_PBOOK
unsigned char *save_framebuffer;
@@ -214,27 +217,28 @@ static int chips_get_cmap(struct fb_cmap *cmap, int kspc, int con,
if (con == currcon) /* current console? */
return fb_get_cmap(cmap, kspc, chipsfb_getcolreg, info);
if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
- else
- fb_copy_cmap(fb_default_cmap(256), cmap, kspc? 0: 2);
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+ else {
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+ }
return 0;
}
static int chips_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- struct display *disp = &fb_display[con];
int err;
- if (disp->cmap.len == 0) {
- err = fb_alloc_cmap(&disp->cmap, 256, 0);
- if (err)
+ if (!fb_display[con].cmap.len) { /* no colormap allocated? */
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
return err;
}
-
- if (con == currcon)
+ if (con == currcon) /* current console? */
return fb_set_cmap(cmap, kspc, chipsfb_setcolreg, info);
- fb_copy_cmap(cmap, &disp->cmap, kspc==0);
+ else
+ fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
}
@@ -244,24 +248,21 @@ static int chips_ioctl(struct inode *inode, struct file *file, u_int cmd,
return -EINVAL;
}
-static int chipsfb_switch(int con, struct fb_info *info)
+static int chipsfbcon_switch(int con, struct fb_info *info)
{
struct fb_info_chips *p = (struct fb_info_chips *) info;
- struct display* old_disp = &fb_display[currcon];
- struct display* new_disp = &fb_display[con];
- int bit_depth;
+ int new_bpp, old_bpp;
+ /* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&old_disp->cmap, 1, chipsfb_getcolreg, info);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, chipsfb_getcolreg, info);
- bit_depth = new_disp->var.bits_per_pixel;
- if (old_disp->var.bits_per_pixel != bit_depth)
- {
- currcon = con;
- chips_set_bitdepth(p, new_disp, con, bit_depth);
- }
- else
- currcon = con;
+ new_bpp = fb_display[con].var.bits_per_pixel;
+ old_bpp = fb_display[currcon].var.bits_per_pixel;
+ currcon = con;
+
+ if (new_bpp != old_bpp)
+ chips_set_bitdepth(p, &fb_display[con], con, new_bpp);
do_install_cmap(con, info);
return 0;
@@ -277,9 +278,10 @@ static void chipsfb_blank(int blank, struct fb_info *info)
struct fb_info_chips *p = (struct fb_info_chips *) info;
int i;
- if (blank > 1) {
+ // used to disable backlight only for blank > 1, but it seems
+ // useful at blank = 1 too (saves battery, extends backlight life)
+ if (blank) {
pmu_enable_backlight(0);
- } else if (blank) {
for (i = 0; i < 256; ++i) {
out_8(p->io_base + 0x3c8, i);
udelay(1);
@@ -311,10 +313,8 @@ static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct fb_info_chips *p = (struct fb_info_chips *) info;
- int hr;
- hr = (p->fix.visual != FB_VISUAL_PSEUDOCOLOR)? (regno << 3): regno;
- if (hr > 255)
+ if (regno > 255)
return 1;
red >>= 8;
green >>= 8;
@@ -322,18 +322,18 @@ static int chipsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
p->palette[regno].red = red;
p->palette[regno].green = green;
p->palette[regno].blue = blue;
- out_8(p->io_base + 0x3c8, hr);
+ out_8(p->io_base + 0x3c8, regno);
udelay(1);
out_8(p->io_base + 0x3c9, red);
out_8(p->io_base + 0x3c9, green);
out_8(p->io_base + 0x3c9, blue);
#ifdef FBCON_HAS_CFB16
- if (regno < 16)
- p->fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;
+ if (regno < 16) p->fbcon_cfb16_cmap[regno] =
+ ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | ((blue & 0xf8) >> 3);
#endif
- return 0;
+ return 0;
}
static void do_install_cmap(int con, struct fb_info *info)
@@ -356,13 +356,14 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
if (bpp == 16) {
if (con == currcon) {
- write_cr(0x13, 200); // 16 bit display width (decimal)
- write_xr(0x81, 0x14); // 15 bit (TrueColor) color mode
+ write_cr(0x13, 200); // Set line length (doublewords)
+ write_xr(0x81, 0x14); // 15 bit (555) color mode
+ write_xr(0x82, 0x00); // Disable palettes
write_xr(0x20, 0x10); // 16 bit blitter mode
}
fix->line_length = 800*2;
- fix->visual = FB_VISUAL_DIRECTCOLOR;
+ fix->visual = FB_VISUAL_TRUECOLOR;
var->red.offset = 10;
var->green.offset = 5;
@@ -377,8 +378,9 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
#endif
} else if (bpp == 8) {
if (con == currcon) {
- write_cr(0x13, 100); // 8 bit display width (decimal)
+ write_cr(0x13, 100); // Set line length (doublewords)
write_xr(0x81, 0x12); // 8 bit color mode
+ write_xr(0x82, 0x08); // Graphics gamma enable
write_xr(0x20, 0x00); // 8 bit blitter mode
}
@@ -400,7 +402,7 @@ static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, in
disp->visual = fix->visual;
disp->var = *var;
-#ifdef CONFIG_PMAC_PBOOK
+#if (defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_FB_COMPAT_XPMAC))
display_info.depth = bpp;
display_info.pitch = fix->line_length;
#endif
@@ -547,9 +549,17 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
int i;
strcpy(p->fix.id, "C&T 65550");
- p->fix.smem_start = (char *) p->chips_base_phys;
- p->fix.smem_len = 800 * 600;
- p->fix.mmio_start = (char *) p->chips_io_phys;
+ p->fix.smem_start = (char *) p->frame_buffer_phys;
+
+// FIXME: Assumes 1MB frame buffer, but 65550 supports 1MB or 2MB.
+// * "3500" PowerBook G3 (the original PB G3) has 2MB.
+// * 2400 has 1MB composed of 2 Mitsubishi M5M4V4265CTP DRAM chips.
+// Motherboard actually supports 2MB -- there are two blank locations
+// for a second pair of DRAMs. (Thanks, Apple!)
+// * 3400 has 1MB (I think). Don't know if it's expandable.
+// -- Tim Seufert
+ p->fix.smem_len = 0x100000; // 1MB
+ p->fix.mmio_start = (char *) p->io_base_phys;
p->fix.type = FB_TYPE_PACKED_PIXELS;
p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
p->fix.line_length = 800;
@@ -572,7 +582,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
p->disp.cmap.green = NULL;
p->disp.cmap.blue = NULL;
p->disp.cmap.transp = NULL;
- p->disp.screen_base = (char *) p->frame_buffer;
+ p->disp.screen_base = p->frame_buffer;
p->disp.visual = p->fix.visual;
p->disp.type = p->fix.type;
p->disp.type_aux = p->fix.type_aux;
@@ -587,7 +597,7 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
p->info.disp = &p->disp;
p->info.fontname[0] = 0;
p->info.changevar = NULL;
- p->info.switch_con = &chipsfb_switch;
+ p->info.switch_con = &chipsfbcon_switch;
p->info.updatevar = &chipsfb_updatevar;
p->info.blank = &chipsfb_blank;
p->info.flags = FBINFO_FLAG_DEFAULT;
@@ -604,7 +614,8 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
return;
}
- printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node));
+ printk("fb%d: Chips 65550 frame buffer (%dK RAM detected)\n",
+ GET_FB_IDX(p->info.node), p->fix.smem_len / 1024);
chips_hw_init(p);
@@ -617,10 +628,10 @@ __initfunc(static void init_chips(struct fb_info_chips *p))
display_info.mode = VMODE_800_600_60;
strncpy(display_info.name, "chips65550",
sizeof(display_info.name));
- display_info.fb_address = p->chips_base_phys + 0x800000;
- display_info.cmap_adr_address = p->chips_io_phys + 0x3c8;
- display_info.cmap_data_address = p->chips_io_phys + 0x3c9;
- display_info.disp_reg_address = p->chips_base_phys + 0xc00000;
+ display_info.fb_address = p->frame_buffer_phys;
+ display_info.cmap_adr_address = p->io_base_phys + 0x3c8;
+ display_info.cmap_data_address = p->io_base_phys + 0x3c9;
+ display_info.disp_reg_address = p->blitter_regs_phys;
console_fb_info = &p->info;
}
#endif /* CONFIG_FB_COMPAT_XPMAC */
@@ -659,17 +670,23 @@ __initfunc(void chips_of_init(struct device_node *dp))
return;
memset(p, 0, sizeof(*p));
addr = dp->addrs[0].address;
- p->chips_base_phys = addr;
- p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_NO_CACHE);
- p->blitter_regs = ioremap(addr + 0xC00000, 0x1000);
+#ifdef __BIG_ENDIAN
+ addr += 0x800000; // Use big-endian aperture
+#endif
+ p->frame_buffer_phys = addr;
+ p->frame_buffer = __ioremap(addr, 0x200000, _PAGE_NO_CACHE);
+ p->blitter_regs_phys = addr + 0x400000;
+ p->blitter_regs = ioremap(addr + 0x400000, 0x1000);
+ p->blitter_data_phys = addr + 0x410000;
+ p->blitter_data = ioremap(addr + 0x410000, 0x10000);
if (pci_device_loc(dp, &bus, &devfn) == 0) {
pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
cmd |= 3; /* enable memory and IO space */
pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
- p->io_base = (unsigned char *) pci_io_base(bus);
+ p->io_base = (__u8 *) pci_io_base(bus);
/* XXX really want the physical address here */
- p->chips_io_phys = (unsigned long) pci_io_base(bus);
+ p->io_base_phys = (unsigned long) pci_io_base(bus);
}
/* Clear the entire framebuffer */
diff --git a/drivers/video/clgenfb.c b/drivers/video/clgenfb.c
index 68078c091..6e09ae666 100644
--- a/drivers/video/clgenfb.c
+++ b/drivers/video/clgenfb.c
@@ -16,6 +16,7 @@
#include <asm/amigahw.h>
#include <asm/pgtable.h>
#include <asm/delay.h>
+#include <asm/io.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
@@ -1533,15 +1534,13 @@ __initfunc(void clgenfb_init(void))
/* begin of the board, but the begin of RAM. */
/* for P4, map in its address space in 2 chunks (### TEST! ) */
/* (note the ugly hardcoded 16M number) */
- fb_info->regs = (unsigned char *)kernel_map(board_addr, 16777216,
- KERNELMAP_NOCACHE_SER, NULL);
+ fb_info->regs = ioremap(board_addr, 16777216);
DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs);
fb_info->regs += 0x600000;
fb_info->fbregs_phys = board_addr + 0x600000;
fb_info->fbmem_phys = board_addr + 16777216;
- fb_info->fbmem = kernel_map(fb_info->fbmem_phys, 16777216,
- KERNELMAP_NOCACHE_SER, NULL);
+ fb_info->fbmem = ioremap(fb_info->fbmem_phys, 16777216);
DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
}
else
@@ -1551,8 +1550,7 @@ __initfunc(void clgenfb_init(void))
fb_info->fbmem_phys = board_addr;
if (board_addr > 0x01000000)
- fb_info->fbmem = kernel_map(board_addr, board_size,
- KERNELMAP_NOCACHE_SER, NULL);
+ fb_info->fbmem = ioremap(board_addr, board_size);
else
fb_info->fbmem = ZTWO_VADDR(board_addr);
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index d1a63b64f..129c4e396 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -57,12 +57,6 @@
#include "controlfb.h"
-static int currcon = 0;
-static int switching = 0;
-static char fontname[40] __initdata = { 0 };
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
-
struct fb_par_control {
int vmode, cmode;
int xres, yres;
@@ -70,11 +64,25 @@ struct fb_par_control {
int xoffset, yoffset;
};
+#define DIRTY(z) ((x)->z != (y)->z)
+static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y)
+{
+ return (!DIRTY(vmode) && !DIRTY(cmode) && !DIRTY(xres)
+ && !DIRTY(yres) && !DIRTY(vxres) && !DIRTY(vyres)
+ && !DIRTY(xoffset) && !DIRTY(yoffset));
+}
+static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y)
+{
+ return (!DIRTY(bits_per_pixel) && !DIRTY(xres)
+ && !DIRTY(yres) && !DIRTY(xres_virtual)
+ && !DIRTY(yres_virtual));
+}
+
struct fb_info_control {
struct fb_info info;
- struct fb_fix_screeninfo fix;
- struct fb_var_screeninfo var;
- struct display disp;
+/* struct fb_fix_screeninfo fix;
+ struct fb_var_screeninfo var;*/
+ struct display display;
struct fb_par_control par;
struct {
__u8 red, green, blue;
@@ -101,15 +109,7 @@ struct fb_info_control {
} fbcon_cmap;
};
-/*
- * Exported functions
- */
-void control_init(void);
-#ifdef CONFIG_FB_OF
-void control_of_init(struct device_node *dp);
-#endif
-void controlfb_setup(char *options, int *ints);
-
+/******************** Prototypes for exported functions ********************/
static int control_open(struct fb_info *info, int user);
static int control_release(struct fb_info *info, int user);
static int control_get_fix(struct fb_fix_screeninfo *fix, int con,
@@ -127,11 +127,38 @@ static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,
static int control_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, int con, struct fb_info *info);
+
+static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,
+ u_int *blue, u_int *transp, struct fb_info *info);
+static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
+
+/******************** Prototypes for internal functions ********************/
+static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
+ struct fb_info_control *p);
+static void do_install_cmap(int con, struct fb_info *info);
+static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p);
+
+/************************* Internal variables *****************************/
+static int currcon = 0;
+static int par_set = 0;
+static char fontname[40] __initdata = { 0 };
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+
+/*
+ * Exported functions
+ */
+void control_init(void);
+#ifdef CONFIG_FB_OF
+void control_of_init(struct device_node *dp);
+#endif
+void control_setup(char *options, int *ints);
+
static int read_control_sense(struct fb_info_control *p);
static inline int control_vram_reqd(int video_mode, int color_mode);
static void set_control_clock(unsigned char *params);
-static void control_set_hardware(struct fb_info_control *p);
-static void control_par_to_all(struct fb_info_control *p, int init);
+static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par);
static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var);
static int control_var_to_par(struct fb_var_screeninfo *var,
struct fb_par_control *par, const struct fb_info *fb_info);
@@ -139,10 +166,8 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
static void control_init_info(struct fb_info *info, struct fb_info_control *p);
static void control_par_to_display(struct fb_par_control *par,
struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p);
-static void control_init_display(struct display *disp);
-static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
- struct fb_info_control *p);
-static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p);
+
+static int controlfb_updatevar(int con, struct fb_info *info);
static struct fb_ops controlfb_ops = {
control_open,
@@ -156,15 +181,15 @@ static struct fb_ops controlfb_ops = {
control_ioctl
};
-static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,
- u_int *blue, u_int *transp, struct fb_info *info);
-static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
-static void do_install_cmap(int con, struct fb_info *info);
+/******************** The functions for controlfb_ops ********************/
+
+#ifndef MODULE
__openfirmware
+#endif
+/********** Dummies for loading control as a module **********/
static int control_open(struct fb_info *info, int user)
{
@@ -178,25 +203,62 @@ static int control_release(struct fb_info *info, int user)
return 0;
}
+#ifdef MODULE
+int init_module(void)
+{
+ struct device_node *dp;
+
+ printk("Loading...\n");
+ dp = find_devices("control");
+ if (dp != 0)
+ control_of_init(dp);
+ else
+ printk("Failed.\n");
+ printk("Done.\n");
+}
+
+void cleanup_module(void)
+{
+}
+#endif
+
+/*********** Providing our information to the user ************/
+
static int control_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
- struct fb_info_control *cp = (struct fb_info_control *) info;
+ struct fb_info_control *p = (struct fb_info_control *) info;
- *fix = cp->fix;
+ if(!par_set)
+ printk(KERN_ERR "control_get_fix called with unset par!\n");
+ if(con == -1) {
+ control_par_to_fix(&p->par, fix, p);
+ } else {
+ struct fb_par_control par;
+
+ control_var_to_par(&fb_display[con].var, &par, info);
+ control_par_to_fix(&par, fix, p);
+ }
return 0;
}
static int control_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
- struct fb_info_control *cp = (struct fb_info_control *) info;
+ struct fb_info_control *p = (struct fb_info_control *) info;
- *var = cp->var;
+ if(!par_set)
+ printk(KERN_ERR "control_get_var called with unset par!\n");
+ if(con == -1) {
+ control_par_to_var(&p->par, var);
+ } else {
+ *var = fb_display[con].var;
+ }
return 0;
}
/* Sets everything according to var */
+/* No longer safe for use in console switching */
static int control_set_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
@@ -204,53 +266,57 @@ static int control_set_var(struct fb_var_screeninfo *var, int con,
struct display *disp;
struct fb_par_control par;
int depthchange, err;
+ int activate = var->activate;
+
+ disp = (con >= 0) ? &fb_display[con] : info->disp;
- disp = (con >= 0) ? &fb_display[con] : &p->disp;
if((err = control_var_to_par(var, &par, info))) {
- printk (KERN_ERR "Error in control_set_var, calling control_var_to_par: %d.\n", err);
+ printk (KERN_ERR "control_set_var: error calling control_var_to_par: %d.\n", err);
return err;
}
- if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
- /* printk("Not activating, in control_set_var.\n"); */
- control_par_to_var(&par, var);
+ control_par_to_var(&par, var);
+
+ if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
return 0;
- }
+
/* I know, we want to use fb_display[con], but grab certain info from p->var instead. */
-#define DIRTY(x) (p->var.x != var->x)
- depthchange = DIRTY(bits_per_pixel);
- if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) &&
- !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel)) {
- control_par_to_var(&par, var);
- p->var = disp->var = *var;
- return 0;
- }
- /* printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel); */
- /* OK, we're getting here at the right times... */
- p->par = par;
- control_par_to_var(&par, var);
- p->var = *var;
- control_par_to_fix(&par, &p->fix, p);
- control_par_to_display(&par, disp, &p->fix, p);
- p->disp = *disp;
+/* [above no longer true] */
+ depthchange = (disp->var.bits_per_pixel != var->bits_per_pixel);
+ if(!VAR_MATCH(&disp->var, var)) {
+ struct fb_fix_screeninfo fix;
+ control_par_to_fix(&par, &fix, p);
+ control_par_to_display(&par, disp, &fix, p);
+ if(info->changevar)
+ (*info->changevar)(con);
+ } else
+ disp->var = *var;
+ /*p->disp = *disp;*/
+
- if(info->changevar && !switching) /* Don't want to do this if just switching consoles. */
- (*info->changevar)(con);
- if(con == currcon)
- control_set_hardware(p);
- if(depthchange)
+ if(con == currcon || con == -1) {
+ control_set_hardware(p, &par);
+ }
+ if(depthchange) {
if((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
return err;
- if(depthchange || switching)
do_install_cmap(con, info);
+ }
return 0;
}
static int control_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
- if (var->xoffset != 0 || var->yoffset != 0)
+ struct fb_info_control *p = (struct fb_info_control *)info;
+ struct fb_par_control *par = &p->par;
+
+ if (var->xoffset != 0 || var->yoffset+var->yres > var->yres_virtual)
return -EINVAL;
+ fb_display[con].var.yoffset = par->yoffset = var->yoffset;
+ if(con == currcon)
+ out_le32(&p->control_regs->start_addr.r,
+ par->yoffset * (par->vxres << par->cmode));
return 0;
}
@@ -260,7 +326,7 @@ static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con,
if (con == currcon) /* current console? */
return fb_get_cmap(cmap, kspc, controlfb_getcolreg, info);
if (fb_display[con].cmap.len) /* non default colormap? */
- fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
+ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0: 2);
else {
int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
@@ -275,12 +341,11 @@ static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,
int err;
if (disp->cmap.len == 0) {
- int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
err = fb_alloc_cmap(&disp->cmap, size, 0);
if (err)
return err;
}
-
if (con == currcon)
return fb_set_cmap(cmap, kspc, controlfb_setcolreg, info);
fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
@@ -293,30 +358,42 @@ static int control_ioctl(struct inode *inode, struct file *file, u_int cmd,
return -EINVAL;
}
+/******************** End of controlfb_ops implementation ********************/
+/* (new one that is) */
+
+
static int controlfb_switch(int con, struct fb_info *info)
{
+ struct fb_info_control *p = (struct fb_info_control *)info;
+ struct fb_par_control par;
+ int oldcon = currcon;
+
if (fb_display[currcon].cmap.len)
fb_get_cmap(&fb_display[currcon].cmap, 1, controlfb_getcolreg,
info);
currcon = con;
-#if 0
- control_var_to_par(&fb_display[currcon].var, &par, info);
- control_set_par(&par, info); /*STOPPEDHERE - did i define that? */
+
+ control_var_to_par(&fb_display[con].var, &par, info);
+ control_set_hardware(p, &par);
+ control_set_dispsw(&fb_display[con], par.cmode, p);
+
+ if(fb_display[oldcon].var.yoffset != fb_display[con].var.yoffset);
+ controlfb_updatevar(con, info);
+
do_install_cmap(con, info);
-#else
- /* I see no reason not to do this. Minus info->changevar(). */
- /* DOH. This makes control_set_var compare, you guessed it, */
- /* fb_display[con].var (first param), and fb_display[con].var! */
- /* Perhaps I just fixed that... */
- switching = 1;
- control_set_var(&fb_display[con].var, con, info);
- switching = 0;
-#endif
- return 0;
+ return 1;
}
static int controlfb_updatevar(int con, struct fb_info *info)
{
+ struct fb_info_control *p = (struct fb_info_control *)info;
+
+ if(con != currcon)
+ return 0;
+ /* imsttfb blanks the unused bottom of the screen here...hmm. */
+ out_le32(&p->control_regs->start_addr.r,
+ fb_display[con].var.yoffset * fb_display[con].line_length);
+
return 0;
}
@@ -332,10 +409,12 @@ static void controlfb_blank(int blank_mode, struct fb_info *info)
* blank_mode == 3: suspend hsync
* blank_mode == 4: powerdown
*/
-/* [danj] I think there's something fishy about those constants... */
+/* A blank_mode of 1+VESA_NO_BLANKING or 1+VESA_POWERDOWN act alike... */
struct fb_info_control *p = (struct fb_info_control *) info;
int ctrl;
+ if(blank_mode == 1+VESA_NO_BLANKING)
+ blank_mode = 1+VESA_POWERDOWN;
ctrl = ld_le32(&p->control_regs->ctrl.r) | 0x33;
if (blank_mode)
--blank_mode;
@@ -385,25 +464,16 @@ static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
out_8(&p->cmap_regs->lut, blue);
if (regno < 16)
- switch (p->var.bits_per_pixel) {
+ switch (p->par.cmode) {
#ifdef FBCON_HAS_CFB16
- case 16:
-#if 0
- p->fbcon_cmap.cfb16[regno] = (red << 10) | (green << 5) | blue;
-#else
+ case CMODE_16:
p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
-#endif
break;
#endif
#ifdef FBCON_HAS_CFB32
- case 32:
-#if 0
- p->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue;
-#else
+ case CMODE_32:
i = (regno << 8) | regno;
p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
- /* I think */
-#endif
break;
#endif
}
@@ -427,18 +497,12 @@ static void do_install_cmap(int con, struct fb_info *info)
#ifdef CONFIG_FB_COMPAT_XPMAC
extern struct vc_mode display_info;
extern struct fb_info *console_fb_info;
-#if 0
-extern int (*console_setmode_ptr)(struct vc_mode *, int);
-extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int,
- struct fb_info *);
-int console_setmode(struct vc_mode *, int);
-#endif
#endif /* CONFIG_FB_COMPAT_XPMAC */
static inline int control_vram_reqd(int video_mode, int color_mode)
{
return control_reg_init[video_mode-1]->vres
- * control_reg_init[video_mode-1]->pitch[color_mode];
+ * control_reg_init[video_mode-1]->hres << color_mode;
}
static void set_control_clock(unsigned char *params)
@@ -457,7 +521,9 @@ static void set_control_clock(unsigned char *params)
__initfunc(static void init_control(struct fb_info_control *p))
{
- struct fb_par_control *par = &p->par;
+ struct fb_par_control parstruct;
+ struct fb_par_control *par = &parstruct;
+ struct fb_var_screeninfo var;
p->sense = read_control_sense(p);
printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
@@ -482,30 +548,44 @@ __initfunc(static void init_control(struct fb_info_control *p))
printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode);
par->vxres = par->xres = control_reg_init[par->vmode - 1]->hres;
- par->vyres = par->yres = control_reg_init[par->vmode - 1]->vres;
+ par->yres = control_reg_init[par->vmode - 1]->vres;
+ par->vyres = p->total_vram / (par->vxres << par->cmode);
par->xoffset = par->yoffset = 0;
- control_par_to_all(p, 1);
+ control_init_info(&p->info, p);
+
+ par_set = 1; /* Debug */
+
+ control_par_to_var(par, &var);
+ control_set_var(&var, -1, &p->info);
p->info.flags = FBINFO_FLAG_DEFAULT;
if (register_framebuffer(&p->info) < 0) {
kfree(p);
return;
}
- control_set_hardware(p);
printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));
}
+#define STORE_D2(a,d) \
+ out_8(&p->cmap_regs->addr, (a)); \
+ out_8(&p->cmap_regs->d2, (d))
+
/* Now how about actually saying, Make it so! */
/* Some things in here probably don't need to be done each time. */
-static void control_set_hardware(struct fb_info_control *p)
+static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par)
{
struct control_regvals *init;
- struct preg *rp;
+ volatile struct preg *rp;
int flags, ctrl, i;
int vmode, cmode;
+ if(PAR_EQUAL(&p->par, par))
+ return;
+
+ p->par = *par;
+
vmode = p->par.vmode;
cmode = p->par.cmode;
@@ -527,19 +607,20 @@ static void control_set_hardware(struct fb_info_control *p)
set_control_clock(init->clock_params);
- p->cmap_regs->addr = 0x20; p->cmap_regs->d2 = init->radacal_ctrl[cmode];
- p->cmap_regs->addr = 0x21; p->cmap_regs->d2 = p->control_use_bank2 ? 0: 1;
- p->cmap_regs->addr = 0x10; p->cmap_regs->d2 = 0;
- p->cmap_regs->addr = 0x11; p->cmap_regs->d2 = 0;
+ STORE_D2(0x20, init->radacal_ctrl[cmode]);
+ STORE_D2(0x21, p->control_use_bank2 ? 0 : 1);
+ STORE_D2(0x10, 0);
+ STORE_D2(0x11, 0);
rp = &p->control_regs->vswin;
for (i = 0; i < 16; ++i, ++rp)
out_le32(&rp->r, init->regs[i]);
- out_le32(&p->control_regs->pitch.r, init->pitch[cmode]);
+ out_le32(&p->control_regs->pitch.r, init->hres << cmode);
out_le32(&p->control_regs->mode.r, init->mode[cmode]);
out_le32(&p->control_regs->flags.r, flags);
- out_le32(&p->control_regs->start_addr.r, 0);
+ out_le32(&p->control_regs->start_addr.r,
+ par->yoffset * (par->vxres << par->cmode));
out_le32(&p->control_regs->reg18.r, 0x1e5);
out_le32(&p->control_regs->reg19.r, 0);
@@ -556,11 +637,11 @@ static void control_set_hardware(struct fb_info_control *p)
#ifdef CONFIG_FB_COMPAT_XPMAC
/* And let the world know the truth. */
if (!console_fb_info || console_fb_info == &p->info) {
- display_info.height = p->var.yres;
- display_info.width = p->var.xres;
+ display_info.height = p->par.yres;
+ display_info.width = p->par.xres;
display_info.depth = (cmode == CMODE_32) ? 32 :
((cmode == CMODE_16) ? 16 : 8);
- display_info.pitch = p->fix.line_length;
+ display_info.pitch = p->par.vxres << p->par.cmode;
display_info.mode = vmode;
strncpy(display_info.name, "control",
sizeof(display_info.name));
@@ -591,15 +672,6 @@ __initfunc(void control_of_init(struct device_node *dp))
unsigned long addr, size;
int i, bank1, bank2;
-#if 0
- if(dp->next != 0)
- printk("Warning: only using first control display device.\n");
- /* danj: I have a feeling this no longer applies - if we somehow *
- * had two of them, they'd be two framebuffers, right?
- * Yep. - paulus
- */
-#endif
-
if(dp->n_addrs != 2) {
printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);
return;
@@ -629,25 +701,23 @@ __initfunc(void control_of_init(struct device_node *dp))
/* Work out which banks of VRAM we have installed. */
/* danj: I guess the card just ignores writes to nonexistant VRAM... */
- p->frame_buffer[0] = 0x5a;
- p->frame_buffer[1] = 0xc7;
- bank1 = p->frame_buffer[0] == 0x5a && p->frame_buffer[1] == 0xc7;
- p->frame_buffer[0x600000] = 0xa5;
- p->frame_buffer[0x600001] = 0x38;
- bank2 = p->frame_buffer[0x600000] == 0xa5 && p->frame_buffer[0x600001] == 0x38;
+ out_8(&p->frame_buffer[0], 0x5a);
+ out_8(&p->frame_buffer[1], 0xc7);
+ asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0]) : "memory" );
+ bank1 = (in_8(&p->frame_buffer[0]) == 0x5a) && (in_8(&p->frame_buffer[1]) == 0xc7);
+
+ out_8(&p->frame_buffer[0x600000], 0xa5);
+ out_8(&p->frame_buffer[0x600001], 0x38);
+ asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000]) : "memory" );
+ bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xa5)
+ && (in_8(&p->frame_buffer[0x600001]) == 0x38);
+
p->total_vram = (bank1 + bank2) * 0x200000;
/* If we don't have bank 1 installed, we hope we have bank 2 :-) */
p->control_use_bank2 = !bank1;
if (p->control_use_bank2)
p->frame_buffer += 0x600000;
-#ifdef CONFIG_FB_COMPAT_XPMAC
-#if 0
- console_set_cmap_ptr = control_set_cmap;
- console_setmode_ptr = control_console_setmode;
-#endif
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
init_control(p);
}
@@ -655,8 +725,6 @@ __initfunc(void control_of_init(struct device_node *dp))
* Get the monitor sense value.
* Note that this can be called before calibrate_delay,
* so we can't use udelay.
- *
- * Hmm - looking at platinum, should we be calling eieio() here?
*/
static int read_control_sense(struct fb_info_control *p)
{
@@ -685,6 +753,7 @@ static int read_control_sense(struct fb_info_control *p)
return sense;
}
+/*********************** Various translation functions ***********************/
#if 1
/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
static int control_var_to_par(struct fb_var_screeninfo *var,
@@ -726,59 +795,58 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
par->vmode = VMODE_1280_960_75; /* 1280x960, 75Hz */
else if (xres <= 1280 && yres <= 1024)
par->vmode = VMODE_1280_1024_75; /* 1280x1024, 75Hz */
- else
+ else {
+ printk(KERN_ERR "Bad x/y res in var_to_par\n");
return -EINVAL;
+ }
xres = control_reg_init[par->vmode-1]->hres;
yres = control_reg_init[par->vmode-1]->vres;
-/*
+ par->xres = xres;
+ par->yres = yres;
+
if (var->xres_virtual <= xres)
par->vxres = xres;
- else
+ else if(var->xres_virtual > xres) {
+ par->vxres = xres;
+ } else /* NotReached at present */
par->vxres = (var->xres_virtual+7) & ~7;
+
if (var->yres_virtual <= yres)
par->vyres = yres;
else
par->vyres = var->yres_virtual;
- par->xoffset = (var->xoffset+7) & ~7;
- par->yoffset = var->yoffset;
- if (par->xoffset+xres > par->vxres || par->yoffset+yres > par->vyres)
- return -EINVAL;
-*/
-
- /* I'm too chicken to think about virtual */
- /* resolutions just yet. Bok bok. */
-
- /* And I'm too chicken to even figure out what they are. Awk awk. [danj] */
- if (var->xres_virtual > xres || var->yres_virtual > yres
- || var->xoffset != 0 || var->yoffset != 0) {
+ if (var->xoffset > 0 || var->yoffset+yres > par->vyres) {
+ printk(KERN_ERR "Bad offsets in var_to_par\n");
return -EINVAL;
}
- par->xres = xres;
- par->yres = yres;
- par->vxres = xres;
- par->vyres = yres;
- par->xoffset = 0;
- par->yoffset = 0;
+ par->xoffset = (var->xoffset+7) & ~7;
+ par->yoffset = var->yoffset;
+
- if (bpp <= 8)
+ if (bpp <= 8)
par->cmode = CMODE_8;
else if (bpp <= 16)
par->cmode = CMODE_16;
else if (bpp <= 32)
par->cmode = CMODE_32;
- else
+ else {
+ printk(KERN_ERR "Bad bpp in var_to_par\n");
return -EINVAL;
+ }
- if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram)
+ if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram) {
+ printk(KERN_ERR "Too much VRAM required for vmode %d cmode %d.\n", par->vmode, par->cmode);
return -EINVAL;
+ }
/* Check if we know about the wanted video mode */
init = control_reg_init[par->vmode-1];
if (init == NULL) {
+ printk(KERN_ERR "init is null in control_var_to_par().\n");
/* I'm not sure if control has any specific requirements -- */
/* if we have a regvals struct, we're good to go? */
return -EINVAL;
@@ -812,14 +880,19 @@ static int control_var_to_par(struct fb_var_screeninfo *var,
}
#endif
-#if 1
+/*********** Convert hardware data in par to an fb_var_screeninfo ***********/
+
static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
{
+ struct control_regints *rv;
+
+ rv = (struct control_regints *) control_reg_init[par->vmode - 1]->regs;
+
memset(var, 0, sizeof(*var));
var->xres = control_reg_init[par->vmode - 1]->hres;
var->yres = control_reg_init[par->vmode - 1]->vres;
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres; /* For now. */
+ var->xres_virtual = par->vxres;
+ var->yres_virtual = par->vyres;
var->xoffset = par->xoffset;
var->yoffset = par->yoffset;
var->grayscale = 0;
@@ -873,12 +946,30 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni
var->width = -1;
var->vmode = FB_VMODE_NONINTERLACED;
- /* these are total guesses, copied right out of atyfb.c */
- var->left_margin = var->right_margin = 64;
- var->upper_margin = var->lower_margin = 32;
- var->hsync_len = /*64*/8;
- var->vsync_len = /*2*/8;
- var->sync = 0;
+ var->left_margin = (rv->heblank - rv->hesync)
+ << ((par->vmode > 18) ? 2 : 1);
+ var->right_margin = (rv->hssync - rv->hsblank)
+ << ((par->vmode > 18) ? 2 : 1);
+ var->hsync_len = (rv->hperiod + 2 - rv->hssync + rv->hesync)
+ << ((par->vmode > 18) ? 2 : 1);
+
+ var->upper_margin = (rv->veblank - rv->vesync) >> 1;
+ var->lower_margin = (rv->vssync - rv->vsblank) >> 1;
+ var->vsync_len = (rv->vperiod - rv->vssync + rv->vesync) >> 1;
+
+ /* Acording to macmodes.c... */
+ if((par->vmode >= 9 && par->vmode <= 12) ||
+ (par->vmode >= 16 && par->vmode <= 18) ||
+ (par->vmode == 20))
+ {
+ var->sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
+ } else {
+ var->sync = 0; /* I suppose */
+ }
+
+ /* The reason these are both here: with my revised margin calculations, */
+ /* these SHOULD both give the same answer for each mode. Some day I */
+ /* will sit down and check the rest. Works perfectly for vmode 13. */
#if 0
/* jonh's pixclocks...*/
@@ -899,14 +990,9 @@ static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeni
var->pixclock >>= control_reg_init[par->vmode-1]->clock_params[2];
#endif
}
-#else
-static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
-{
- mac_vmode_to_var(par->vmode, par->cmode, var);
-}
-#endif
-static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p)
+static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
+ struct fb_info_control *p)
{
memset(fix, 0, sizeof(*fix));
strcpy(fix->id, "control");
@@ -914,34 +1000,35 @@ static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_contr
fix->mmio_len = sizeof(struct control_regs);
fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->ypanstep = 1;
/*
fix->type_aux = 0;
fix->ywrapstep = 0;
fix->ypanstep = 0;
fix->xpanstep = 0;
*/
-}
-/* Fix must already be inited ^^^^^^^ */
-static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
- struct fb_info_control *p)
-{
fix->smem_start = (void *)(p->frame_buffer_phys
+ control_reg_init[par->vmode-1]->offset[par->cmode]);
- p->fix.smem_len = control_vram_reqd(par->vmode, par->cmode);
- /* Hmm, jonh used total_vram here. */
- p->fix.visual = (par->cmode == CMODE_8) ?
+ fix->smem_len = p->total_vram;
+ fix->visual = (par->cmode == CMODE_8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
- p->fix.line_length = par->vxres << par->cmode;
- /* ywrapstep, xpanstep, ypanstep */
+ fix->line_length = par->vxres << par->cmode;
}
-static void control_init_display(struct display *disp)
+/* We never initialize any display except for p->disp.
+ And p->disp is already memset to 0. So no memset here.
+ [Found by Takashi Oe]
+*/
+static void control_par_to_display(struct fb_par_control *par,
+ struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p)
{
- memset(disp, 0, sizeof(*disp));
- disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS;
+ /* memset(disp, 0, sizeof(*disp)); */
+ disp->type = fix->type;
disp->can_soft_blank = 1;
- disp->scrollmode = SCROLL_YREDRAW;
+ disp->scrollmode = SCROLL_YNOMOVE | SCROLL_YNOPARTIAL;
+ disp->ypanstep = fix->ypanstep;
+ disp->ywrapstep = fix->ywrapstep;
#if 0
disp->type_aux = fix->type_aux;
disp->cmap.red = NULL; /* ??? danj */
@@ -950,22 +1037,18 @@ static void control_init_display(struct display *disp)
disp->cmap.transp = NULL;
/* Yeah, I realize I just set 0 = 0. */
#endif
-}
-static void control_par_to_display(struct fb_par_control *par,
- struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p)
-{
- disp->var = p->var;
+ control_par_to_var(par, &disp->var);
disp->screen_base = (char *) p->frame_buffer
+ control_reg_init[par->vmode-1]->offset[par->cmode];
disp->visual = fix->visual;
disp->line_length = fix->line_length;
-
-if(disp->scrollmode != SCROLL_YREDRAW) {
- printk(KERN_ERR "Scroll mode not YREDRAW in control_par_to_display!!\n");
- disp->scrollmode = SCROLL_YREDRAW;
+ control_set_dispsw(disp, par->cmode, p);
}
- switch (par->cmode) {
+
+static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p)
+{
+ switch (cmode) {
#ifdef FBCON_HAS_CFB8
case CMODE_8:
disp->dispsw = &fbcon_cfb8;
@@ -991,10 +1074,10 @@ if(disp->scrollmode != SCROLL_YREDRAW) {
static void control_init_info(struct fb_info *info, struct fb_info_control *p)
{
- strcpy(info->modename, p->fix.id);
+ strcpy(info->modename, "control");
info->node = -1; /* ??? danj */
info->fbops = &controlfb_ops;
- info->disp = &p->disp;
+ info->disp = &p->display;
strcpy(info->fontname, fontname);
info->changevar = NULL;
info->switch_con = &controlfb_switch;
@@ -1002,28 +1085,8 @@ static void control_init_info(struct fb_info *info, struct fb_info_control *p)
info->blank = &controlfb_blank;
}
-/* danj: Oh, I HOPE I didn't miss anything major in here... */
-static void control_par_to_all(struct fb_info_control *p, int init)
-{
- if(init) {
- control_init_fix(&p->fix, p);
- }
- control_par_to_fix(&p->par, &p->fix, p);
-
- control_par_to_var(&p->par, &p->var);
-
- if(init) {
- control_init_display(&p->disp);
- }
- control_par_to_display(&p->par, &p->disp, &p->fix, p);
-
- if(init) {
- control_init_info(&p->info, p);
- }
-}
-
/* Parse user speficied options (`video=controlfb:') */
-__initfunc(void controlfb_setup(char *options, int *ints))
+__initfunc(void control_setup(char *options, int *ints))
{
char *this_opt;
@@ -1050,6 +1113,11 @@ __initfunc(void controlfb_setup(char *options, int *ints))
} else if (!strncmp(this_opt, "cmode:", 6)) {
int depth = simple_strtoul(this_opt+6, NULL, 0);
switch (depth) {
+ case CMODE_8:
+ case CMODE_16:
+ case CMODE_32:
+ default_cmode = depth;
+ break;
case 8:
default_cmode = CMODE_8;
break;
@@ -1081,4 +1149,5 @@ static int controlfb_pan_display(struct fb_var_screeninfo *var,
return 0;
}
+
#endif
diff --git a/drivers/video/controlfb.h b/drivers/video/controlfb.h
index 32943ed27..ea8c36105 100644
--- a/drivers/video/controlfb.h
+++ b/drivers/video/controlfb.h
@@ -73,6 +73,28 @@ struct control_regs {
struct preg res[6];
};
+struct control_regints {
+ /* Vertical parameters are in units of 1/2 scan line */
+ unsigned vswin; /* between vsblank and vssync */
+ unsigned vsblank; /* vert start blank */
+ unsigned veblank; /* vert end blank (display start) */
+ unsigned vewin; /* between vesync and veblank */
+ unsigned vesync; /* vert end sync */
+ unsigned vssync; /* vert start sync */
+ unsigned vperiod; /* vert period */
+ unsigned reg8;
+ /* Horizontal params are in units of 2 pixels */
+ /* Except, apparently, for hres > 1024 (or == 1280?) */
+ unsigned hperiod; /* horiz period - 2 */
+ unsigned hsblank; /* horiz start blank */
+ unsigned heblank; /* horiz end blank */
+ unsigned hesync; /* horiz end sync */
+ unsigned hssync; /* horiz start sync */
+ unsigned rege;
+ unsigned regf;
+ unsigned reg10;
+};
+
/*
* Register initialization tables for the control display.
*
@@ -81,9 +103,10 @@ struct control_regs {
*
* The values for vertical frequency (V) in the comments below
* are the values measured using the modes under MacOS.
+ *
+ * Pitch is always the same as bytes per line (for these video modes at least).
*/
struct control_regvals {
- int pitch[3]; /* bytes/line, indexed by color_mode */
int offset[3]; /* first pixel address */
unsigned regs[16]; /* for vswin .. reg10 */
unsigned char mode[3]; /* indexed by color_mode */
@@ -95,7 +118,6 @@ struct control_regvals {
/* Register values for 1280x1024, 75Hz mode (20) */
static struct control_regvals control_reg_init_20 = {
- { 1280, 2560, 0 },
{ 0x10, 0x20, 0 },
{ 2129, 2128, 80, 42, 4, 2130, 2132, 88,
420, 411, 91, 35, 421, 18, 211, 386, },
@@ -107,7 +129,6 @@ static struct control_regvals control_reg_init_20 = {
/* Register values for 1280x960, 75Hz mode (19) */
static struct control_regvals control_reg_init_19 = {
- { 1280, 2560, 0 },
{ 0x10, 0x20, 0 },
{ 1997, 1996, 76, 40, 4, 1998, 2000, 86,
418, 409, 89, 35, 419, 18, 210, 384, },
@@ -119,7 +140,6 @@ static struct control_regvals control_reg_init_19 = {
/* Register values for 1152x870, 75Hz mode (18) */
static struct control_regvals control_reg_init_18 = {
- { 1152, 2304, 4608 },
{ 0x10, 0x28, 0x50 },
{ 1825, 1822, 82, 43, 4, 1828, 1830, 120,
726, 705, 129, 63, 727, 32, 364, 664 },
@@ -131,7 +151,6 @@ static struct control_regvals control_reg_init_18 = {
/* Register values for 1024x768, 75Hz mode (17) */
static struct control_regvals control_reg_init_17 = {
- { 1024, 2048, 4096 },
{ 0x10, 0x28, 0x50 },
{ 1603, 1600, 64, 34, 4, 1606, 1608, 120,
662, 641, 129, 47, 663, 24, 332, 616 },
@@ -141,9 +160,8 @@ static struct control_regvals control_reg_init_17 = {
1024, 768
};
-/* Register values for 1024x768, 72Hz mode (16 (15?)) */
-static struct control_regvals control_reg_init_16 = {
- { 1024, 2048, 4096 },
+/* Register values for 1024x768, 72Hz mode 16 (15?) */
+static struct control_regvals control_reg_init_15 = {
{ 0x10, 0x28, 0x50 },
{ 1607, 1604, 68, 39, 10, 1610, 1612, 132,
670, 653, 141, 67, 671, 34, 336, 604, },
@@ -155,7 +173,6 @@ static struct control_regvals control_reg_init_16 = {
/* Register values for 1024x768, 60Hz mode (14) */
static struct control_regvals control_reg_init_14 = {
- { 1024, 2048, 4096 },
{ 0x10, 0x28, 0x50 },
{ 1607, 1604, 68, 39, 10, 1610, 1612, 132,
670, 653, 141, 67, 671, 34, 336, 604, },
@@ -167,7 +184,6 @@ static struct control_regvals control_reg_init_14 = {
/* Register values for 832x624, 75Hz mode (13) */
static struct control_regvals control_reg_init_13 = {
- { 832, 1664, 3328 },
{ 0x10, 0x28, 0x50 },
{ 1331, 1330, 82, 43, 4, 1332, 1334, 128,
574, 553, 137, 31, 575, 16, 288, 544 },
@@ -178,7 +194,6 @@ static struct control_regvals control_reg_init_13 = {
/* Register values for 800x600, 75Hz mode (12) */
static struct control_regvals control_reg_init_12 = {
- { 800, 1600, 3200 },
{ 0x10, 0x28, 0x50 },
{ 1247, 1246, 46, 25, 4, 1248, 1250, 104,
526, 513, 113, 39, 527, 20, 264, 488, },
@@ -189,7 +204,6 @@ static struct control_regvals control_reg_init_12 = {
/* Register values for 800x600, 72Hz mode (11) */
static struct control_regvals control_reg_init_11 = {
- { 800, 1600, 3200 },
{ 0x10, 0x28, 0x50 },
{ 1293, 1256, 56, 33, 10, 1330, 1332, 76,
518, 485, 85, 59, 519, 30, 260, 460, },
@@ -200,7 +214,6 @@ static struct control_regvals control_reg_init_11 = {
/* Register values for 800x600, 60Hz mode (10) */
static struct control_regvals control_reg_init_10 = {
- { 800, 1600, 3200 },
{ 0x10, 0x28, 0x50 },
{ 1293, 1256, 56, 33, 10, 1330, 1332, 76,
518, 485, 85, 59, 519, 30, 260, 460, },
@@ -211,7 +224,6 @@ static struct control_regvals control_reg_init_10 = {
/* Register values for 640x870, 75Hz Full Page Display (7) */
static struct control_regvals control_reg_init_7 = {
- { 640, 1280, 2560 },
{ 0x10, 0x30, 0x68 },
{ 0x727, 0x724, 0x58, 0x2e, 0x4, 0x72a, 0x72c, 0x40,
0x19e, 0x18c, 0x4c, 0x27, 0x19f, 0x14, 0xd0, 0x178 },
@@ -222,7 +234,6 @@ static struct control_regvals control_reg_init_7 = {
/* Register values for 640x480, 67Hz mode (6) */
static struct control_regvals control_reg_init_6 = {
- { 640, 1280, 2560 },
{ 0, 8, 0x10 },
{ 1045, 1042, 82, 43, 4, 1048, 1050, 72,
430, 393, 73, 31, 431, 16, 216, 400 },
@@ -233,7 +244,6 @@ static struct control_regvals control_reg_init_6 = {
/* Register values for 640x480, 60Hz mode (5) */
static struct control_regvals control_reg_init_5 = {
- { 640, 1280, 2560 },
{ 0x10, 0x28, 0x50 },
{ 1037, 1026, 66, 34, 2, 1048, 1050, 56,
398, 385, 65, 47, 399, 24, 200, 352, },
@@ -253,8 +263,8 @@ static struct control_regvals *control_reg_init[VMODE_MAX] = {
&control_reg_init_12,
&control_reg_init_13,
&control_reg_init_14,
- &control_reg_init_16,
- &control_reg_init_16,
+ &control_reg_init_15,
+ &control_reg_init_15,
&control_reg_init_17,
&control_reg_init_18,
&control_reg_init_19,
diff --git a/drivers/video/creatorfb.c b/drivers/video/creatorfb.c
index 6c8f14b1d..69242992d 100644
--- a/drivers/video/creatorfb.c
+++ b/drivers/video/creatorfb.c
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.15 1998/09/04 15:43:40 jj Exp $
+/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
* creatorfb.c: Creator/Creator3D frame buffer driver
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -123,7 +123,12 @@
#define FFB_ROP_NEW 0x83
#define FFB_UCSR_FIFO_MASK 0x00000fff
+#define FFB_UCSR_FB_BUSY 0x01000000
#define FFB_UCSR_RP_BUSY 0x02000000
+#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
+#define FFB_UCSR_READ_ERR 0x40000000
+#define FFB_UCSR_FIFO_OVFL 0x80000000
+#define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
struct ffb_fbc {
/* Next vertex registers */
@@ -271,6 +276,30 @@ struct ffb_fbc {
volatile u32 mer;
};
+static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
+{
+ int limit = 10000;
+
+ do {
+ if((ffb->ucsr & FFB_UCSR_FIFO_MASK) >= (n + 4))
+ break;
+ if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+ ffb->ucsr = FFB_UCSR_ALL_ERRORS;
+ } while(--limit > 0);
+}
+
+static __inline__ void FFBWait(struct ffb_fbc *ffb)
+{
+ int limit = 10000;
+
+ do {
+ if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
+ break;
+ if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+ ffb->ucsr = FFB_UCSR_ALL_ERRORS;
+ } while(--limit > 0);
+}
+
struct ffb_dac {
volatile u32 type;
volatile u32 value;
@@ -313,6 +342,8 @@ static void ffb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
int x, y, w, h;
+ FFBWait(fbc);
+ FFBFifo(fbc, 6);
fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
fbc->drawop = FFB_DRAWOP_RECTANGLE;
@@ -337,9 +368,12 @@ static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
{
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+ FFBWait(fbc);
+ FFBFifo(fbc, 2);
fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
fbc->drawop = FFB_DRAWOP_RECTANGLE;
while (count-- > 0) {
+ FFBFifo(fbc, 4);
fbc->by = boxes[1];
fbc->bx = boxes[0];
fbc->bh = boxes[3] - boxes[1];
@@ -370,11 +404,14 @@ static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int
xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
else
xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
+ FFBWait(fbc);
+ FFBFifo(fbc, 5);
fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
fbc->fontw = fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
+ FFBFifo(fbc, fontheight(p));
if (fontwidth(p) <= 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = *fd++ << 24;
@@ -394,6 +431,8 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
int i, xy;
u8 *fd1, *fd2, *fd3, *fd4;
+ FFBWait(fbc);
+ FFBFifo(fbc, 2);
fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
xy = fb->s.ffb.xy_margin;
@@ -408,6 +447,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
if (fontwidth(p) <= 8) {
while (count >= 4) {
count -= 4;
+ FFBFifo(fbc, 3);
fbc->fontw = 4 * fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
@@ -422,6 +462,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
}
+ FFBFifo(fbc, fontheight(p));
if (fontwidth(p) == 8) {
for (i = 0; i < fontheight(p); i++)
fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
@@ -437,6 +478,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
} else {
while (count >= 2) {
count -= 2;
+ FFBFifo(fbc, 3);
fbc->fontw = 2 * fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
@@ -447,6 +489,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
}
+ FFBFifo(fbc, fontheight(p));
for (i = 0; i < fontheight(p); i++) {
fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
fd1 += 2; fd2 += 2;
@@ -456,6 +499,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
}
while (count) {
count--;
+ FFBFifo(fbc, 3);
fbc->fontw = fontwidth(p);
fbc->fontinc = 0x10000;
fbc->fontxy = xy;
@@ -463,6 +507,7 @@ static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned sh
i = ((*s++ & p->charmask) << fontheightlog(p));
else
i = ((*s++ & p->charmask) * fontheight(p));
+ FFBFifo(fbc, fontheight(p));
if (fontwidth(p) <= 8) {
fd1 = p->fontdata + i;
for (i = 0; i < fontheight(p); i++)
@@ -573,10 +618,13 @@ static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
{
register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+ FFBWait(fbc);
+ FFBFifo(fbc, 4);
fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
fbc->fbc = 0x2000707f;
fbc->rop = FFB_ROP_NEW;
fbc->pmask = 0xffffffff;
+ FFBWait(fbc);
}
static char idstring[60] __initdata = { 0 };
@@ -588,7 +636,9 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
struct display *disp = &fb->disp;
struct fbtype *type = &fb->type;
struct linux_prom64_registers regs[2*PROMREG_MAX];
- int i;
+ int i, afb = 0;
+ unsigned int btype;
+ char name[64];
if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
return NULL;
@@ -597,10 +647,22 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
if (!disp->dispsw_data)
return NULL;
memset(disp->dispsw_data, 0, 16 * sizeof(u32));
+
+ prom_getstring(fb->prom_node, "name", name, sizeof(name));
+ if (!strcmp(name, "SUNW,afb"))
+ afb = 1;
- strcpy(fb->info.modename, "Creator");
+ btype = prom_getintdefault(fb->prom_node, "board_type", 0);
- strcpy(fix->id, "Creator");
+ strcpy(fb->info.modename, "Creator");
+ if (!afb) {
+ if ((btype & 7) == 3)
+ strcpy(fix->id, "Creator 3D");
+ else
+ strcpy(fix->id, "Creator");
+ } else
+ strcpy(fix->id, "Elite 3D");
+
fix->visual = FB_VISUAL_TRUECOLOR;
fix->line_length = 8192;
fix->accel = FB_ACCEL_SUN_CREATOR;
@@ -625,6 +687,12 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
fb->switch_from_graph = ffb_switch_from_graph;
fb->fill = ffb_fill;
+ /* If there are any read errors or fifo overflow conditions,
+ * clear them now.
+ */
+ if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+ fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
+
ffb_switch_from_graph(fb);
fb->physbase = regs[0].phys_addr;
@@ -640,7 +708,7 @@ __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
i = prom_getintdefault (fb->prom_node, "board_type", 8);
- sprintf(idstring, "Creator at %016lx type %d DAC %d", regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+ sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
return idstring;
}
diff --git a/drivers/video/cvisionppc.h b/drivers/video/cvisionppc.h
new file mode 100644
index 000000000..4a137548f
--- /dev/null
+++ b/drivers/video/cvisionppc.h
@@ -0,0 +1,51 @@
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * $Id: cvisionppc.h,v 1.1.2.1 1999/01/12 19:52:59 geert Exp $
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef CVISIONPPC_H
+#define CVISIONPPC_H
+
+#ifndef PM2FB_H
+#include "pm2fb.h"
+#endif
+
+struct cvppc_par {
+ unsigned char* pci_config;
+ unsigned char* pci_bridge;
+ unsigned long user_flags;
+};
+
+#define CSPPC_PCI_BRIDGE 0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN 0x0000
+#define CSPPC_BRIDGE_INT 0x0010
+
+#define CVPPC_PCI_CONFIG 0xfffc0000
+#define CVPPC_ROM_ADDRESS 0xe2000001
+#define CVPPC_REGS_REGION 0xef000000
+#define CVPPC_FB_APERTURE_ONE 0xe0000000
+#define CVPPC_FB_APERTURE_TWO 0xe1000000
+#define CVPPC_FB_SIZE 0x00800000
+#define CVPPC_MEM_CONFIG_OLD 0xed61fcaa /* FIXME Fujitsu?? */
+#define CVPPC_MEM_CONFIG_NEW 0xed41c532 /* FIXME USA?? */
+#define CVPPC_MEMCLOCK 83000 /* in KHz */
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN 0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2 0x01
+
+#endif /* CVISIONPPC_H */
+
+/*****************************************************************************
+ * That's all folks!
+ *****************************************************************************/
diff --git a/drivers/video/cvppcfb.c b/drivers/video/cvppcfb.c
deleted file mode 100644
index 3e786ab61..000000000
--- a/drivers/video/cvppcfb.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * CybervisionPPC (TVP4020) low level driver for the frame buffer device
- * ^^^^^^^^^
- * literally ;)
- *
- * Copyright (c) 1998 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) (v124)
- * --------------------------------------------------------------------------
- * based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven
- * --------------------------------------------------------------------------
- * TODO h/w parameters detect/modify, 8-bit CLUT, acceleration
- * --------------------------------------------------------------------------
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file README.legal in the main directory of this archive
- * for more details.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/amigahw.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
-#include <asm/setup.h>
-#include <asm/io.h>
-
-#define ISDIGIT(a) ((a)>='0' && (a)<='9')
-
-#undef CVPPCFB_MASTER_DEBUG
-#ifdef CVPPCFB_MASTER_DEBUG
-#define FBEGIN if (usr_startup.debug>1)\
- printk(__FUNCTION__ " {\n")
-#define FEND if (usr_startup.debug>1)\
- printk("} /* " __FUNCTION__ " */\n")
-#define DPRINTK(a,b...) if (usr_startup.debug)\
- printk("%s: " a, __FUNCTION__ , ## b)
-#else
-#define FBEGIN
-#define FEND
-#define DPRINTK(a,b...)
-#endif
-
-static const char cvppcfb_name[16]="CybervisionPPC";
-
-struct cvppcfb_startup { /* startup options */
- char font[40];
- u32 xres;
- u32 yres;
- u32 bpp;
- unsigned long debug;
- unsigned long YANW; /* You Are Not Welcome */
- struct fb_monspecs monitor;
-};
-static struct cvppcfb_startup usr_startup = {
- "\0", 640, 480, 16, 0, 1, { 31, 32, 58, 62, 0 } };
-
-#define CVPPC_BASE 0xe0000000
-#define CVPPC_SIZE 0x00800000
-static char* video_base; /* virtual address of board video memory */
-static unsigned long video_phys;/* physical address of board video memory */
-static u32 video_size; /* size of board video memory */
-
-struct cvppcfb_par { /* board parameters (sort of) */
- u32 xres;
- u32 yres;
- u32 vxres;
- u32 vyres;
- u32 vxoff;
- u32 vyoff;
- u32 bpp;
- u32 clock;
- u32 sflags;
- u32 left;
- u32 right;
- u32 top;
- u32 bottom;
- u32 hsynclen;
- u32 vsynclen;
-};
-
-struct cvppcfb_info {
- struct fb_info_gen gen;
- struct cvppcfb_par current_par;
- int current_par_valid;
- struct display disp;
- struct {
- u8 transp;
- u8 red;
- u8 green;
- u8 blue;
- } palette[256];
- union {
-#ifdef FBCON_HAS_CFB16
- u16 cmap16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
- u32 cmap32[16];
-#endif
- } cmap;
-};
-static struct cvppcfb_info fb_info;
-
-/*
- * declaration of hw switch functions
- */
-static void cvppcfb_detect(void);
-static int cvppcfb_encode_fix(struct fb_fix_screeninfo* fix,
- const void* par, struct fb_info_gen* info);
-static int cvppcfb_decode_var(const struct fb_var_screeninfo* var,
- void* par, struct fb_info_gen* info);
-static int cvppcfb_encode_var(struct fb_var_screeninfo* var,
- const void* par, struct fb_info_gen* info);
-static void cvppcfb_get_par(void* par, struct fb_info_gen* info);
-static void cvppcfb_set_par(const void* par, struct fb_info_gen* info);
-static int cvppcfb_getcolreg(unsigned regno,
- unsigned* red, unsigned* green, unsigned* blue,
- unsigned* transp, struct fb_info* info);
-static int cvppcfb_setcolreg(unsigned regno,
- unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info* info);
-static void cvppcfb_dispsw(const void* par, struct display* disp,
- struct fb_info_gen* info);
-
-static struct fbgen_hwswitch cvppcfb_hwswitch={
- cvppcfb_detect, cvppcfb_encode_fix, cvppcfb_decode_var,
- cvppcfb_encode_var, cvppcfb_get_par, cvppcfb_set_par,
- cvppcfb_getcolreg, cvppcfb_setcolreg, NULL /* pan_display() */,
- NULL /* blank() */, cvppcfb_dispsw
-};
-
-/*
- * declaration of ops switch functions
- */
-static int cvppcfb_open(struct fb_info* info, int user);
-static int cvppcfb_release(struct fb_info* info, int user);
-
-static struct fb_ops cvppcfb_ops={
- cvppcfb_open, cvppcfb_release, fbgen_get_fix, fbgen_get_var,
- fbgen_set_var, fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display,
- fbgen_ioctl, NULL /* fb_mmap() */
-};
-
-/*
- * the actual definition of the above mentioned functions follows
- */
-
-/*
- * private functions
- */
-
-static void cvppcfb_set_modename(struct cvppcfb_info* info,
- struct cvppcfb_startup* s) {
-
- strcpy(info->gen.info.modename, cvppcfb_name);
-}
-
-static void cvppcfb_decode_opt(struct cvppcfb_startup* s, void* par,
- struct cvppcfb_info* info) {
- struct cvppcfb_par* p=(struct cvppcfb_par* )par;
-
- memset(p, 0, sizeof(struct cvppcfb_par));
- p->xres=p->vxres=(s->xres+7)&~7;
- p->yres=p->vyres=s->yres;
- p->bpp=(s->bpp+7)&~7;
- if (p->bpp==24)
- p->bpp=32;
- if (p->bpp<32)
- p->clock=6666;
- else
- p->clock=10000;
-}
-
-static void cvppcfb_encode_mcap(char* options, struct fb_monspecs* mcap) {
- char* next;
- int i=0;
-
- while (i<4 && options) {
- if ((next=strchr(options, ';')))
- *(next++)='\0';
- switch (i++) {
- case 0: /* vmin */
- mcap->vfmin=(__u16 )
- simple_strtoul(options, NULL, 0);
- break;
- case 1: /* vmax */
- mcap->vfmax=(__u16 )
- simple_strtoul(options, NULL, 0);
- break;
- case 2: /* hmin */
- mcap->hfmin=(__u32 )
- simple_strtoul(options, NULL, 0);
- break;
- case 3: /* hmax */
- mcap->hfmax=(__u32 )
- simple_strtoul(options, NULL, 0);
- break;
- }
- options=next;
- }
-}
-
-static void cvppcfb_encode_mode(char* options, struct cvppcfb_startup* s) {
- char* next;
- int i=0;
-
- while (i<3 && options) {
- if ((next=strchr(options, ';')))
- *(next++)='\0';
- switch (i++) {
- case 0:
- s->xres=(u32 )
- simple_strtoul(options, NULL, 0);
- break;
- case 1:
- s->yres=(u32 )
- simple_strtoul(options, NULL, 0);
- break;
- case 2:
- s->bpp=(u32 )
- simple_strtoul(options, NULL, 0);
- break;
- }
- options=next;
- }
-}
-
-/*
- * protected functions
- */
-
-static void cvppcfb_detect(void) {
-
- FBEGIN;
- FEND;
-}
-
-static int cvppcfb_encode_fix(struct fb_fix_screeninfo* fix,
- const void* par, struct fb_info_gen* info) {
-
- FBEGIN;
- strcpy(fix->id, cvppcfb_name);
- fix->smem_start=(char* )video_phys;
- fix->smem_len=(__u32 )video_size;
- fix->type=FB_TYPE_PACKED_PIXELS;
- if (((struct cvppcfb_par* )par)->bpp==8)
- fix->visual=FB_VISUAL_PSEUDOCOLOR;
- else
- fix->visual=FB_VISUAL_TRUECOLOR;
- fix->xpanstep=fix->ypanstep=fix->ywrapstep=0;
- fix->line_length=0; /* computed by fbcon */
- fix->mmio_start=NULL;
- fix->mmio_len=0;
- fix->accel=FB_ACCEL_NONE;
- FEND;
- return 0;
-}
-
-static int cvppcfb_decode_var(const struct fb_var_screeninfo* var,
- void* par, struct fb_info_gen* info) {
- struct cvppcfb_par p;
-
- FBEGIN;
- memset(&p, 0, sizeof(struct cvppcfb_par));
- p.bpp=(var->bits_per_pixel+7)&~7;
- if (p.bpp==24)
- p.bpp=32;
- if (p.bpp>32) {
- DPRINTK("depth too big (%lu)\n", p.bpp);
- return -EINVAL;
- }
- p.xres=(var->xres+7)&~7;
- p.yres=var->yres;
- if (p.xres<320 || p.yres<200 || p.xres>2048 || p.yres>2048) {
- DPRINTK("bad resolution (%lux%lu)\n", p.xres, p.yres);
- return -EINVAL;
- }
- p.vxres=(var->xres_virtual+7)&~7;
- p.vxoff=(var->xoffset+7)&~7;
- p.vyres=var->yres_virtual;
- p.vyoff=var->yoffset;
- if (p.vxres<p.xres+p.vxoff)
- p.vxres=p.xres+p.vxoff;
- if (p.vyres<p.yres+p.vyoff)
- p.vyres=p.yres+p.vyoff;
- if (p.vxres*p.vyres*p.bpp/8>video_size) {
- DPRINTK("no memory for screen (%lux%lux%lu)\n",
- p.vxres, p.vyres, p.bpp);
- return -EINVAL;
- }
- p.sflags=var->sync&(FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT);
- p.clock=var->pixclock;
- if (p.clock<6666) {
- DPRINTK("pixclock too fast (%lu)\n", p.clock);
- return -EINVAL;
- }
- p.left=var->left_margin;
- p.top=var->upper_margin;
- p.right=var->right_margin;
- p.bottom=var->lower_margin;
- p.hsynclen=var->hsync_len;
- p.vsynclen=var->vsync_len;
- *((struct cvppcfb_par* )par)=p;
- FEND;
- return 0;
-}
-
-static int cvppcfb_encode_var(struct fb_var_screeninfo* var,
- const void* par, struct fb_info_gen* info) {
- struct cvppcfb_par* p=(struct cvppcfb_par* )par;
- struct fb_var_screeninfo v;
-
- FBEGIN;
- memset(&v, 0, sizeof(struct fb_var_screeninfo));
- v.xres=p->xres;
- v.yres=p->yres;
- v.xres_virtual=p->vxres;
- v.yres_virtual=p->vyres;
- v.xoffset=p->vxoff;
- v.yoffset=p->vyoff;
- v.bits_per_pixel=p->bpp;
- switch (p->bpp) {
- case 16:
- v.red.offset=11;
- v.red.length=5;
- v.green.offset=5;
- v.green.length=6;
- v.blue.length=5;
- break;
- case 32:
- v.transp.offset=24;
- v.red.offset=16;
- v.green.offset=8;
- v.transp.length=8;
- /* fallback */
- case 8:
- v.red.length=v.green.length=v.blue.length=8;
- break;
- }
- v.activate=FB_ACTIVATE_NOW;
- v.height=v.width=-1;
- v.pixclock=p->clock;
- v.left_margin=p->left;
- v.right_margin=p->right;
- v.upper_margin=p->top;
- v.lower_margin=p->bottom;
- v.hsync_len=p->hsynclen;
- v.vsync_len=p->vsynclen;
- v.sync=p->sflags;
- v.vmode=FB_VMODE_NONINTERLACED;
- *var=v;
- FEND;
- return 0;
-}
-
-static void cvppcfb_get_par(void* par, struct fb_info_gen* info) {
- struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
- FBEGIN;
- if (i->current_par_valid)
- *((struct cvppcfb_par* )par)=i->current_par;
- else
- cvppcfb_decode_opt(&usr_startup, par, i);
- FEND;
-}
-
-static void cvppcfb_set_par(const void* par, struct fb_info_gen* info) {
- struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
- FBEGIN;
- i->current_par=*((struct cvppcfb_par* )par);
- i->current_par_valid=1;
- FEND;
-}
-
-static int cvppcfb_getcolreg(unsigned regno,
- unsigned* red, unsigned* green, unsigned* blue,
- unsigned* transp, struct fb_info* info) {
- struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
- if (regno<256) {
- *red=i->palette[regno].red<<8|i->palette[regno].red;
- *green=i->palette[regno].green<<8|i->palette[regno].green;
- *blue=i->palette[regno].blue<<8|i->palette[regno].blue;
- *transp=i->palette[regno].transp<<8|i->palette[regno].transp;
- }
- return regno>255;
-}
-
-static int cvppcfb_setcolreg(unsigned regno,
- unsigned red, unsigned green, unsigned blue,
- unsigned transp, struct fb_info* info) {
- struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
- if (regno<16) {
- switch (i->current_par.bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- DPRINTK("8 bit depth not supported yet.\n");
- return 1;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- i->cmap.cmap16[regno]=
- ((u32 )red & 0xf800) |
- (((u32 )green & 0xfc00)>>5) |
- (((u32 )blue & 0xf800)>>11);
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- i->cmap.cmap32[regno]=
- (((u32 )transp & 0xff00) << 16) |
- (((u32 )red & 0xff00) << 8) |
- (((u32 )green & 0xff00)) |
- (((u32 )blue & 0xff00) >> 8);
- break;
-#endif
- }
- }
- if (regno<256) {
- i->palette[regno].red=red >> 8;
- i->palette[regno].green=green >> 8;
- i->palette[regno].blue=blue >> 8;
- i->palette[regno].transp=transp >> 8;
- }
- return regno>255;
-}
-
-static void cvppcfb_dispsw(const void* par, struct display* disp,
- struct fb_info_gen* info) {
- struct cvppcfb_info* i=(struct cvppcfb_info* )info;
- unsigned long flags;
-
- FBEGIN;
- save_flags(flags);
- cli();
- switch (((struct cvppcfb_par* )par)->bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- disp->dispsw=&fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- disp->dispsw=&fbcon_cfb16;
- disp->dispsw_data=i->cmap.cmap16;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- disp->dispsw=&fbcon_cfb32;
- disp->dispsw_data=i->cmap.cmap32;
- break;
-#endif
- default:
- disp->dispsw=&fbcon_dummy;
- break;
- }
- restore_flags(flags);
- FEND;
-}
-
-static int cvppcfb_open(struct fb_info* info, int user) {
-
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int cvppcfb_release(struct fb_info* info, int user) {
-
- MOD_DEC_USE_COUNT;
- return 0;
-}
-
-/*
- * public functions
- */
-
-void cvppcfb_cleanup(struct fb_info* info) {
-
- unregister_framebuffer(info);
-}
-
-__initfunc(void cvppcfb_init(void)) {
-
- FBEGIN;
-#ifdef CVPPCFB_MASTER_DEBUG
- printk("cvppcfb_init():\n");
- printk(" resolution %ldx%ldx%ld\n", usr_startup.xres,
- usr_startup.yres, usr_startup.bpp);
- printk(" debug: %ld, YANW: %ld\n", usr_startup.debug,
- usr_startup.YANW);
- printk(" monitorcap: %ld,%ld,%ld,%ld\n",
- usr_startup.monitor.vfmin, usr_startup.monitor.vfmax,
- usr_startup.monitor.hfmin, usr_startup.monitor.hfmax);
-#endif
- if (usr_startup.YANW) /* cannot probe yet */
- return;
- memset(&fb_info, 0, sizeof(struct cvppcfb_info));
- video_size=CVPPC_SIZE;
- video_phys=CVPPC_BASE;
-#ifdef CONFIG_APUS
- video_base=(char* )
- kernel_map(video_phys, video_size, KERNELMAP_NOCACHE_SER, NULL);
-#else
- video_base=ioremap(video_phys, video_size);
-#endif
- DPRINTK("video_phys=%08lx, video_base=%08lx\n", video_phys, video_base);
- DPRINTK("phys_to_virt(video_phys)=%08lx\n", phys_to_virt(video_phys));
- DPRINTK("virt_to_phys(video_base)=%08lx\n", virt_to_phys(video_base));
- fb_info.disp.scrollmode=SCROLL_YREDRAW;
- fb_info.gen.parsize=sizeof(struct cvppcfb_par);
- fb_info.gen.fbhw=&cvppcfb_hwswitch;
- cvppcfb_set_modename(&fb_info, &usr_startup);
- fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
- fb_info.gen.info.fbops=&cvppcfb_ops;
- fb_info.gen.info.monspecs=usr_startup.monitor;
- fb_info.gen.info.disp=&fb_info.disp;
- strcpy(fb_info.gen.info.fontname, usr_startup.font);
- fb_info.gen.info.switch_con=&fbgen_switch;
- fb_info.gen.info.updatevar=&fbgen_update_var;
- fb_info.gen.info.blank=&fbgen_blank;
- fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
- if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0) {
- printk( "cvppcfb: bad startup configuration: "
- "unable to register.\n");
- return;
- }
- fbgen_set_disp(-1, &fb_info.gen);
- fbgen_install_cmap(0, &fb_info.gen);
- if (register_framebuffer(&fb_info.gen.info)<0) {
- printk("cvppcfb: unable to register.\n");
- return;
- }
- printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
- GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,
- (unsigned long )(video_size>>10));
- MOD_INC_USE_COUNT;
- FEND;
-}
-
-__initfunc(void cvppcfb_setup(char* options, int* ints)) {
- char* next;
-
- usr_startup.YANW=0;
- DPRINTK("options: '%s'\n", options);
- while (options) {
- if ((next=strchr(options, ',')))
- *(next++)='\0';
- if (!strncmp(options, "monitorcap:", 11))
- cvppcfb_encode_mcap(options+11, &usr_startup.monitor);
- else if (!strncmp(options, "debug:", 6)) {
- if (ISDIGIT(options[6]))
- usr_startup.debug=options[6]-'0';
- else
- usr_startup.debug=1;
- }
- else if (!strncmp(options, "mode:", 5))
- cvppcfb_encode_mode(options+5, &usr_startup);
- else if (!strncmp(options, "font:", 5))
- strcpy(usr_startup.font, options+5);
- else
- DPRINTK("unrecognized option '%s'\n", options);
- options=next;
- }
-#ifdef CVPPCFB_MASTER_DEBUG
- printk("cvppcfb_setup():\n");
- printk(" resolution %ldx%ldx%ld\n", usr_startup.xres,
- usr_startup.yres, usr_startup.bpp);
- printk(" debug: %ld, YANW: %ld\n", usr_startup.debug,
- usr_startup.YANW);
- printk(" monitorcap: %ld,%ld,%ld,%ld\n",
- usr_startup.monitor.vfmin, usr_startup.monitor.vfmax,
- usr_startup.monitor.hfmin, usr_startup.monitor.hfmax);
-#endif
-}
-
-/*
- * modularization
- */
-
-#ifdef MODULE
-int init_module(void) {
-
- cvppcfb_init();
-}
-
-void cleanup_module(void) {
-
- cvppcfb_cleanup();
-}
-#endif /* MODULE */
-
diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c
index 80ec1481b..6882ebfb0 100644
--- a/drivers/video/cyberfb.c
+++ b/drivers/video/cyberfb.c
@@ -166,6 +166,8 @@ static unsigned char Cyber_colour_table [256][3];
static unsigned long CyberMem;
static unsigned long CyberSize;
static volatile char *CyberRegs;
+static unsigned long CyberMem_phys;
+static unsigned long CyberRegs_phys;
/* From cvision.c for cvision_core.c */
static unsigned long cv64_mem;
static unsigned long cv64_fbmem;
@@ -428,9 +430,9 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
DPRINTK("ENTER\n");
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id, cyberfb_name);
- fix->smem_start = (char*) virt_to_phys ((void *)CyberMem);
+ fix->smem_start = (char*) CyberMem_phys;
fix->smem_len = CyberSize;
- fix->mmio_start = (char*) virt_to_phys ((void *)CyberRegs);
+ fix->mmio_start = (char*) CyberRegs_phys;
fix->mmio_len = 0x10000;
fix->type = FB_TYPE_PACKED_PIXELS;
@@ -1144,8 +1146,7 @@ __initfunc(void cyberfb_init(void))
DPRINTK("board_addr=%08lx\n", board_addr);
DPRINTK("board_size=%08lx\n", board_size);
- cv64_mem = kernel_map (board_addr, board_size, KERNELMAP_NOCACHE_SER,
- NULL);
+ cv64_mem = ioremap(board_addr, board_size);
cv64_regs = (volatile char *)(cv64_mem + 0x02000000);
cv64_fbmem = cv64_mem + 0x01400000;
DPRINTK("cv64_mem=%08lx cv64_regs=%08lx cv64_fbmem=%08lx\n",
@@ -1153,6 +1154,8 @@ __initfunc(void cyberfb_init(void))
CyberMem = cv64_fbmem;
CyberRegs = cv64_regs;
+ CyberMem_phys = board_addr + 0x01400000;
+ CyberRegs_phys = CyberMem_phys + 0x00c00000;
DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem,
(long unsigned int)CyberRegs);
@@ -1453,7 +1456,7 @@ unsigned char cvconscolors[16][3] = { /* background, foreground, hilite */
/* -------------------- Hardware specific routines ------------------------- */
#if 0
/* ARB Generates 100 usec delay */
-inline void __delay (unsigned long usecs)
+inline void __cv_delay (unsigned long usecs)
{
int k;
@@ -1493,7 +1496,7 @@ inline unsigned char RAttr (volatile caddr_t board, short idx)
{
vgaw (board, ACT_ADDRESS_W, idx);
udelay(100);
- /* __delay (0); */
+ /* __cv_delay (0); */
return (vgar (board, ACT_ADDRESS_R));
}
@@ -1895,7 +1898,7 @@ static void cv64_board_init (void)
vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x07);
vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x1000);
udelay(200);
- /* __delay (200000); */
+ /* __cv_delay (200000); */
vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x2000);
Cyber_WaitBlit();
/* GfxBusyWait (cv64_regs); */
@@ -1903,7 +1906,7 @@ static void cv64_board_init (void)
Cyber_WaitBlit();
/* GfxBusyWait (cv64_regs); */
udelay(200);
- /* __delay (200000); */
+ /* __cv_delay (200000); */
vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF);
Cyber_WaitBlit();
/* GfxBusyWait (cv64_regs); */
@@ -1961,7 +1964,9 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
int xres, hfront, hsync, hback;
int yres, vfront, vsync, vback;
int bpp;
+#if 0
float freq_f;
+#endif
long freq;
/* ---------------- */
@@ -2066,9 +2071,15 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
/* cv64_compute_clock accepts arguments in Hz */
/* pixclock is in ps ... convert to Hz */
+#if 0
freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
freq = ((long) freq_f) * 1000;
-
+#else
+/* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
+ */
+ freq = (1000000000 / video_mode->pixclock) * 1000;
+#endif
+
mnr = cv64_compute_clock (freq);
WSeq (cv64_regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
WSeq (cv64_regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
@@ -2257,14 +2268,14 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
udelay(100);
- /* __delay (100000); */
+ /* __cv_delay (100000); */
WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
udelay(100);
- /* __delay (100000); */
+ /* __cv_delay (100000); */
WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA,
(video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
udelay(100);
- /* __delay (100000); */
+ /* __cv_delay (100000); */
tfillm = (96 * (cv64_memclk / 1000)) / 240000;
@@ -2296,7 +2307,7 @@ static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, m);
WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, n);
udelay(10);
- /* __delay (10000); */
+ /* __cv_delay (10000); */
/* Text initialization */
diff --git a/drivers/video/cyberfb.h b/drivers/video/cyberfb.h
index 232bc6857..bce02a462 100644
--- a/drivers/video/cyberfb.h
+++ b/drivers/video/cyberfb.h
@@ -421,7 +421,7 @@ do { \
/* --------------------------------- */
/* in cvision_core.c */
-inline void __delay(unsigned long usecs);
+inline void __cv_delay(unsigned long usecs);
inline void GfxBusyWait(volatile caddr_t board);
inline void GfxFifoWait(volatile caddr_t board);
inline unsigned char RAttr(volatile caddr_t board, short idx);
diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c
index 5fe78bc30..bfa98c719 100644
--- a/drivers/video/fbcon-cfb8.c
+++ b/drivers/video/fbcon-cfb8.c
@@ -143,12 +143,12 @@ void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy,
case 12:
case 16:
for (rows = fontheight(p) ; rows-- ; dest += bytes) {
- ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
- ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
- ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
+ ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
+ ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+ ((u32 *)dest)[2]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
if (fontwidth(p) == 16)
((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
- cdat += 2;
+ cdat++;
}
break;
}
@@ -200,12 +200,12 @@ void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
cdat = p->fontdata + (c * fontheight(p) << 1);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
- ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
- ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
- ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
+ ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
+ ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+ ((u32 *)dest)[2]= (nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx;
if (fontwidth(p) == 16)
((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
- cdat += 2;
+ cdat++;
}
dest0+=fontwidth(p);
}
diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/fbcon-iplan2p2.c
index c8d6838be..0c0bfa21f 100644
--- a/drivers/video/fbcon-iplan2p2.c
+++ b/drivers/video/fbcon-iplan2p2.c
@@ -10,7 +10,6 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
@@ -18,6 +17,7 @@
#include <linux/fb.h>
#include <asm/byteorder.h>
+#include <asm/setup.h>
#include <video/fbcon.h>
#include <video/fbcon-iplan2p2.h>
@@ -43,7 +43,7 @@ static const u8 color_2p[] = { 0, 0, 0, 1, 0, 1, 1, 1, 2, 2, 2, 3, 2, 3, 3, 3 };
/* Perform the m68k movepw operation. */
static inline void movepw(u8 *d, u16 val)
{
-#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060
+#if defined __mc68000__ && !defined CPU_M68060_ONLY
asm volatile ("movepw %1,%0@(0)" : : "a" (d), "d" (val));
#else
d[0] = (val >> 16) & 0xff;
diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c
index 04b4a8422..2c1d67a77 100644
--- a/drivers/video/fbcon-iplan2p4.c
+++ b/drivers/video/fbcon-iplan2p4.c
@@ -10,7 +10,6 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
@@ -18,6 +17,7 @@
#include <linux/fb.h>
#include <asm/byteorder.h>
+#include <asm/setup.h>
#include <video/fbcon.h>
#include <video/fbcon-iplan2p4.h>
@@ -35,7 +35,7 @@
/* Perform the m68k movepl operation. */
static inline void movepl(u8 *d, u32 val)
{
-#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060
+#if defined __mc68000__ && !defined CPU_M68060_ONLY
asm volatile ("movepl %1,%0@(0)" : : "a" (d), "d" (val));
#else
d[0] = (val >> 24) & 0xff;
diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/fbcon-iplan2p8.c
index dbdd56ac8..c730eb39c 100644
--- a/drivers/video/fbcon-iplan2p8.c
+++ b/drivers/video/fbcon-iplan2p8.c
@@ -10,7 +10,6 @@
* more details.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
@@ -18,6 +17,7 @@
#include <linux/fb.h>
#include <asm/byteorder.h>
+#include <asm/setup.h>
#include <video/fbcon.h>
#include <video/fbcon-iplan2p8.h>
@@ -40,7 +40,7 @@
/* Perform the m68k movepl operation extended to 64 bits. */
static inline void movepl2(u8 *d, u32 val1, u32 val2)
{
-#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060
+#if defined __mc68000__ && !defined CPU_M68060_ONLY
asm volatile ("movepl %1,%0@(0); movepl %2,%0@(8)"
: : "a" (d), "d" (val1), "d" (val2));
#else
diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c
index 9bdc9020b..033118f61 100644
--- a/drivers/video/fbcon.c
+++ b/drivers/video/fbcon.c
@@ -536,13 +536,14 @@ static void fbcon_setup(int con, int init, int logo)
conp->vc_can_do_color = p->var.bits_per_pixel != 1;
conp->vc_complement_mask = conp->vc_can_do_color ? 0x7700 : 0x0800;
if (charcnt == 256) {
- p->conp->vc_hi_font_mask = 0;
+ conp->vc_hi_font_mask = 0;
p->fgshift = 8;
p->bgshift = 12;
p->charmask = 0xff;
} else {
- p->conp->vc_hi_font_mask = 0x100;
- p->conp->vc_complement_mask <<= 1;
+ conp->vc_hi_font_mask = 0x100;
+ if (conp->vc_can_do_color)
+ conp->vc_complement_mask <<= 1;
p->fgshift = 9;
p->bgshift = 13;
p->charmask = 0x1ff;
@@ -944,7 +945,8 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
{
int unit = conp->vc_num;
struct display *p = &fb_display[unit];
- int is_txt = (p->type == FB_TYPE_TEXT);
+ int scroll_partial = !(p->scrollmode & __SCROLL_YNOPARTIAL);
+ int logos_left = 0; int logos_width = conp->vc_cols;
if (!p->can_soft_blank && console_blanked)
return 0;
@@ -962,22 +964,34 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
switch (dir) {
case SM_UP:
+ /* K.Garloff@ping.de, 98/10/21: If logo is diplayed, only save logo
+ * and not the hole top region. In combination with the logo being
+ * displayed on the right side, this allows scrollback feature
+ * when bootlogo is displayed. */
+ if (t != 0 && logo_shown == fg_console) {
+ struct display *p = &fb_display[unit];
+ int lw = (smp_num_cpus * (LOGO_W + 8) - 7) / fontwidth(p) + 1;
+ logos_left = conp->vc_cols - lw;
+ while (logos_left < 0) logos_left += (LOGO_W + 8 - 7) / fontwidth(p);
+ logos_width = conp->vc_cols - logos_left;
+ }
if (count > conp->vc_rows) /* Maximum realistic size */
count = conp->vc_rows;
switch (p->scrollmode & __SCROLL_YMASK) {
case __SCROLL_YMOVE:
- p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+ if (t > 0) p->dispsw->bmove(p, 0, logos_left, count,
+ logos_left, t, logos_width);
+ p->dispsw->bmove(p, count, 0, 0, 0, b-count,
conp->vc_cols);
- p->dispsw->clear(conp, p, b-count, 0, count,
+ p->dispsw->clear(conp, p, b-count, 0, count,
conp->vc_cols);
break;
case __SCROLL_YWRAP:
- if (b-t-count > 3*conp->vc_rows>>2) {
+ if (b-t-count > 2*conp->vc_rows/3) {
if (t > 0)
- fbcon_bmove(conp, 0, 0, count, 0, t,
- conp->vc_cols);
- ywrap_up(unit, conp, p, count);
+ fbcon_bmove(conp, 0, logos_left, count, logos_left, t, logos_width);
+ ywrap_up(unit, conp, p, count);
if (conp->vc_rows-b > 0)
fbcon_bmove(conp, b-count, 0, b, 0,
conp->vc_rows-b, conp->vc_cols);
@@ -990,11 +1004,11 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
break;
case __SCROLL_YPAN:
- if (( is_txt && (b-t == conp->vc_rows)) ||
- (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
+ if (( !scroll_partial && (b-t == conp->vc_rows)) ||
+ ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) {
if (t > 0)
- fbcon_bmove(conp, 0, 0, count, 0, t,
- conp->vc_cols);
+ fbcon_bmove(conp, 0, logos_left, count, logos_left, t,
+ logos_width);
ypan_up(unit, conp, p, count);
if (conp->vc_rows-b > 0)
fbcon_bmove(conp, b-count, 0, b, 0,
@@ -1049,8 +1063,8 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,
break;
case __SCROLL_YPAN:
- if (( is_txt && (b-t == conp->vc_rows)) ||
- (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
+ if (( !scroll_partial && (b-t == conp->vc_rows)) ||
+ ( scroll_partial && (b-t-count > 3*conp->vc_rows>>2))) {
if (conp->vc_rows-b > 0)
fbcon_bmove(conp, b, 0, b-count, 0,
conp->vc_rows-b, conp->vc_cols);
@@ -1250,46 +1264,41 @@ static inline int fbcon_get_font(int unit, struct console_font_op *op)
if (!op->data) return 0;
if (op->width <= 8) {
+ j = fontheight(p);
for (i = 0; i < op->charcount; i++) {
- for (j = 0; j < fontheight(p); j++)
- *data++ = *fontdata++;
- memset(data, 0, 32-j);
- data += 32 - j;
+ memcpy(data, fontdata, j);
+ memset(data+j, 0, 32-j);
+ data += 32;
+ fontdata += j;
}
}
#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
else if (op->width <= 16) {
+ j = fontheight(p) * 2;
for (i = 0; i < op->charcount; i++) {
- for (j = 0; j < fontheight(p); j++) {
- *data++ = *(u16 *)fontdata >> 8;
- *data++ = *(u16 *)fontdata;
- fontdata += sizeof(u16);
- }
- memset(data, 0, 2*(32-j));
- data += 2 * (32 - j);
+ memcpy(data, fontdata, j);
+ memset(data+j, 0, 64-j);
+ data += 64;
+ fontdata += j;
}
} else if (op->width <= 24) {
for (i = 0; i < op->charcount; i++) {
for (j = 0; j < fontheight(p); j++) {
- *data++ = *(u32 *)fontdata >> 24;
- *data++ = *(u32 *)fontdata >> 16;
- *data++ = *(u32 *)fontdata >> 8;
+ *data++ = fontdata[0];
+ *data++ = fontdata[1];
+ *data++ = fontdata[2];
fontdata += sizeof(u32);
}
memset(data, 0, 3*(32-j));
data += 3 * (32 - j);
}
} else {
+ j = fontheight(p) * 4;
for (i = 0; i < op->charcount; i++) {
- for (j = 0; j < fontheight(p); j++) {
- *data++ = *(u32 *)fontdata >> 24;
- *data++ = *(u32 *)fontdata >> 16;
- *data++ = *(u32 *)fontdata >> 8;
- *data++ = *(u32 *)fontdata;
- fontdata += sizeof(u32);
- }
- memset(data, 0, 4*(32-j));
- data += 4 * (32 - j);
+ memcpy(data, fontdata, j);
+ memset(data+j, 0, 128-j);
+ data += 128;
+ fontdata += j;
}
}
#endif
@@ -1325,16 +1334,58 @@ static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int
p->_fontheight = h;
if (p->conp->vc_hi_font_mask && cnt == 256) {
p->conp->vc_hi_font_mask = 0;
- p->conp->vc_complement_mask >>= 1;
+ if (p->conp->vc_can_do_color)
+ p->conp->vc_complement_mask >>= 1;
p->fgshift--;
p->bgshift--;
p->charmask = 0xff;
+
+ /* ++Edmund: reorder the attribute bits */
+ if (p->conp->vc_can_do_color) {
+ struct vc_data *conp = p->conp;
+ unsigned short *cp = (unsigned short *) conp->vc_origin;
+ int count = conp->vc_screenbuf_size/2;
+ unsigned short c;
+ for (; count > 0; count--, cp++) {
+ c = scr_readw(cp);
+ scr_writew(((c & 0xfe00) >> 1) | (c & 0xff), cp);
+ }
+ c = conp->vc_video_erase_char;
+ conp->vc_video_erase_char = ((c & 0xfe00) >> 1) | (c & 0xff);
+ conp->vc_attr >>= 1;
+ }
+
} else if (!p->conp->vc_hi_font_mask && cnt == 512) {
p->conp->vc_hi_font_mask = 0x100;
- p->conp->vc_complement_mask <<= 1;
+ if (p->conp->vc_can_do_color)
+ p->conp->vc_complement_mask <<= 1;
p->fgshift++;
p->bgshift++;
p->charmask = 0x1ff;
+
+ /* ++Edmund: reorder the attribute bits */
+ {
+ struct vc_data *conp = p->conp;
+ unsigned short *cp = (unsigned short *) conp->vc_origin;
+ int count = conp->vc_screenbuf_size/2;
+ unsigned short c;
+ for (; count > 0; count--, cp++) {
+ unsigned short newc;
+ c = scr_readw(cp);
+ if (conp->vc_can_do_color)
+ newc = ((c & 0xff00) << 1) | (c & 0xff);
+ else
+ newc = c & ~0x100;
+ scr_writew(newc, cp);
+ }
+ c = conp->vc_video_erase_char;
+ if (conp->vc_can_do_color) {
+ conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff);
+ conp->vc_attr <<= 1;
+ } else
+ conp->vc_video_erase_char = c & ~0x100;
+ }
+
}
fbcon_font_widths(p);
@@ -1380,17 +1431,17 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
int w = op->width;
int h = op->height;
int size = h;
- int i, j, k;
- u8 *new_data, *data = op->data, c, *p;
+ int i, k;
#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
- u32 d;
-#else
+ int j;
+#endif
+ u8 *new_data, *data = op->data, *p;
+#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
if (w != 8)
return -EINVAL;
#endif
-
- if (w > 32 || (op->charcount != 256 && op->charcount != 512))
+ if ((w <= 0) || (w > 32) || (op->charcount != 256 && op->charcount != 512))
return -EINVAL;
if (w > 8) {
@@ -1407,56 +1458,46 @@ static inline int fbcon_set_font(int unit, struct console_font_op *op)
FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = op->charcount;
REFCOUNT(new_data) = 0; /* usage counter */
- k = 0;
p = new_data;
if (w <= 8) {
for (i = 0; i < op->charcount; i++) {
- for (j = 0; j < h; j++) {
- c = *data++;
- k += c;
- *p++ = c;
- }
- data += 32 - h;
+ memcpy(p, data, h);
+ data += 32;
+ p += h;
}
}
#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
else if (w <= 16) {
+ h *= 2;
for (i = 0; i < op->charcount; i++) {
- for (j = 0; j < h; j++) {
- d = (data[0] << 8) | data[1];
- data += 2;
- k += d;
- *(u16 *)p = d;
- p += sizeof(u16);
- }
- data += 2*(32 - h);
+ memcpy(p, data, h);
+ data += 64;
+ p += h;
}
- } else {
+ } else if (w <= 24) {
for (i = 0; i < op->charcount; i++) {
for (j = 0; j < h; j++) {
- if (w <= 24) {
- d = (data[0] << 24) |
- (data[1] << 16) |
- (data[2] << 8);
- data += 3;
- } else {
- d = (data[0] << 24) |
- (data[1] << 16) |
- (data[2] << 8) |
- data[3];
- data += 4;
- }
- k += d;
- *(u32 *)p = d;
+ memcpy(p, data, 3);
+ p[3] = 0;
+ data += 3;
p += sizeof(u32);
}
- if (w <= 24)
- data += 3*(32 - h);
- else
- data += 4*(32 - h);
+ data += 3*(32 - h);
+ }
+ } else {
+ h *= 4;
+ for (i = 0; i < op->charcount; i++) {
+ memcpy(p, data, h);
+ data += 128;
+ p += h;
}
}
#endif
+ /* we can do it in u32 chunks because of charcount is 256 or 512, so
+ font length must be multiple of 256, at least. And 256 is multiple
+ of 4 */
+ k = 0;
+ while (p > new_data) k += *--(u32 *)p;
FNTSUM(new_data) = k;
/* Check if the same font is on some other console already */
for (i = 0; i < MAX_NR_CONSOLES; i++) {
@@ -1587,7 +1628,7 @@ static int fbcon_scrolldelta(struct vc_data *conp, int lines)
p->var.xoffset = 0;
p->var.yoffset = offset*fontheight(p);
p->fb_info->updatevar(unit, p->fb_info);
- if (!offset)
+ if (!scrollback_current)
fbcon_cursor(conp, CM_DRAW);
return 0;
}
@@ -1664,8 +1705,8 @@ __initfunc(static int fbcon_show_logo( void ))
logo_depth = 1;
}
- for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&
- x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
+ for (x = p->var.xres - LOGO_W; x > 0 && x > (int)p->var.xres
+ - smp_num_cpus * (LOGO_W + 8); x -= (LOGO_W + 8)) {
#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
@@ -1768,6 +1809,20 @@ __initfunc(static int fbcon_show_logo( void ))
done = 1;
}
#endif
+#if defined(CONFIG_FBCON_CFB4)
+ if (depth == 4 && p->type == FB_TYPE_PACKED_PIXELS) {
+ src = logo;
+ for( y1 = 0; y1 < LOGO_H; y1++) {
+ dst = fb + y1*line + x/2;
+ for( x1 = 0; x1 < LOGO_W/2; x1++) {
+ u8 q = *src++;
+ q = (q << 4) | (q >> 4);
+ *dst++ = q;
+ }
+ }
+ done = 1;
+ }
+#endif
#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FB_SBUS)
if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) {
/* depth 8 or more, packed, with color registers */
@@ -1796,7 +1851,7 @@ __initfunc(static int fbcon_show_logo( void ))
int line_length = p->line_length;
/* for support of Atari interleaved planes */
-#define MAP_X(x) (line_length ? x : (x & ~1)*depth + (x & 1))
+#define MAP_X(x) (line_length ? (x) : ((x) & ~1)*depth + ((x) & 1))
#else
#define MAP_X(x) (x)
#endif
@@ -1807,7 +1862,7 @@ __initfunc(static int fbcon_show_logo( void ))
src = logo;
for( y1 = 0; y1 < LOGO_H; y1++ ) {
for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) {
- dst = fb + y1*line + MAP_X(x1);
+ dst = fb + y1*line + MAP_X(x/8+x1);
for( bit = 0; bit < logo_depth; bit++ ) {
val = 0;
for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) {
@@ -1826,7 +1881,7 @@ __initfunc(static int fbcon_show_logo( void ))
if (depth > logo_depth) {
for( y1 = 0; y1 < LOGO_H; y1++ ) {
for( x1 = 0; x1 < LOGO_LINE; x1++ ) {
- dst = fb + y1*line + MAP_X(x1) + logo_depth*plane;
+ dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane;
for( i = logo_depth; i < depth; i++, dst += plane )
*dst = (i == logo_depth && logo_depth == 4)
? 0xff : 0x00;
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index aab80ad6b..d8e6b0829 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -22,9 +22,7 @@
#include <linux/console.h>
#include <linux/console_struct.h>
#include <linux/init.h>
-#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
-#endif
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
@@ -56,8 +54,8 @@ extern void macfb_init(void);
extern void macfb_setup(char *options, int *ints);
extern void cyberfb_init(void);
extern void cyberfb_setup(char *options, int *ints);
-extern void cvppcfb_init(void);
-extern void cvppcfb_setup(char *options, int *ints);
+extern void pm2fb_init(void);
+extern void pm2fb_setup(char *options, int *ints);
extern void retz3fb_init(void);
extern void retz3fb_setup(char *options, int *ints);
extern void clgenfb_init(void);
@@ -114,8 +112,8 @@ static struct {
#ifdef CONFIG_FB_CYBER
{ "cyber", cyberfb_init, cyberfb_setup },
#endif
-#ifdef CONFIG_FB_CVPPC
- { "cvppcfb", cvppcfb_init, cvppcfb_setup },
+#ifdef CONFIG_FB_PM2
+ { "pm2fb", pm2fb_init, pm2fb_setup },
#endif
#ifdef CONFIG_FB_CLGEN
{ "clgen", clgenfb_init, clgenfb_setup },
@@ -205,7 +203,6 @@ static inline int PROC_CONSOLE(void)
return MINOR(current->tty->device) - 1;
}
-#ifdef CONFIG_PROC_FS
static int fbmem_read_proc(char *buf, char **start, off_t offset,
int len, int *eof, void *private)
{
@@ -220,7 +217,6 @@ static int fbmem_read_proc(char *buf, char **start, off_t offset,
*start = buf + offset;
return len > offset ? len - offset : 0;
}
-#endif
static ssize_t
fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
@@ -583,20 +579,16 @@ unregister_framebuffer(const struct fb_info *fb_info)
return 0;
}
-#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_fbmem;
-#endif
__initfunc(void
fbmem_init(void))
{
int i;
-#ifdef CONFIG_PROC_FS
proc_fbmem = create_proc_entry("fb", 0, 0);
if (proc_fbmem)
proc_fbmem->read_proc = fbmem_read_proc;
-#endif
if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
printk("unable to get major %d for fb devs\n", FB_MAJOR);
diff --git a/drivers/video/font_sun12x22.c b/drivers/video/font_sun12x22.c
index c4cd54c7a..803b35ea8 100644
--- a/drivers/video/font_sun12x22.c
+++ b/drivers/video/font_sun12x22.c
@@ -1,6207 +1,6207 @@
#include <video/font.h>
-#define FONTDATAMAX 5632
+#define FONTDATAMAX 11264
-static unsigned short fontdata_sun12x22[FONTDATAMAX] = {
+static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
/* 0 0x00 '^@' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 1 0x01 '^A' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 2 0x02 '^B' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 3 0x03 '^C' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 4 0x04 '^D' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 5 0x05 '^E' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 6 0x06 '^F' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 7 0x07 '^G' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 8 0x08 '^H' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 9 0x09 '^I' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 10 0x0a '^J' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 11 0x0b '^K' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 12 0x0c '^L' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 13 0x0d '^M' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 14 0x0e '^N' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 15 0x0f '^O' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 16 0x10 '^P' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 17 0x11 '^Q' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 18 0x12 '^R' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 19 0x13 '^S' */
- 0x0000, /* 000000000000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 20 0x14 '^T' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1ff0, /* 000111111111 */
- 0x3cc0, /* 001111001100 */
- 0x7cc0, /* 011111001100 */
- 0x7cc0, /* 011111001100 */
- 0x7cc0, /* 011111001100 */
- 0x3cc0, /* 001111001100 */
- 0x1cc0, /* 000111001100 */
- 0x0cc0, /* 000011001100 */
- 0x0cc0, /* 000011001100 */
- 0x0cc0, /* 000011001100 */
- 0x0cc0, /* 000011001100 */
- 0x0cc0, /* 000011001100 */
- 0x0cc0, /* 000011001100 */
- 0x1ce0, /* 000111001110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xf0, /* 000111111111 */
+ 0x3c, 0xc0, /* 001111001100 */
+ 0x7c, 0xc0, /* 011111001100 */
+ 0x7c, 0xc0, /* 011111001100 */
+ 0x7c, 0xc0, /* 011111001100 */
+ 0x3c, 0xc0, /* 001111001100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x1c, 0xe0, /* 000111001110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 21 0x15 '^U' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f00, /* 000111110000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x1f00, /* 000111110000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x1f00, /* 000111110000 */
- 0x0180, /* 000000011000 */
- 0x0180, /* 000000011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 22 0x16 '^V' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 23 0x17 '^W' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 24 0x18 '^X' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 25 0x19 '^Y' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 26 0x1a '^Z' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 27 0x1b '^[' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 28 0x1c '^\' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 29 0x1d '^]' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 30 0x1e '^^' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 31 0x1f '^_' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 32 0x20 ' ' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 33 0x21 '!' */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 34 0x22 '"' */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 35 0x23 '#' */
- 0x0000, /* 000000000000 */
- 0x0330, /* 000000110011 */
- 0x0330, /* 000000110011 */
- 0x0330, /* 000000110011 */
- 0x0660, /* 000001100110 */
- 0x1ff0, /* 000111111111 */
- 0x1ff0, /* 000111111111 */
- 0x0cc0, /* 000011001100 */
- 0x0cc0, /* 000011001100 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x7fc0, /* 011111111100 */
- 0x7fc0, /* 011111111100 */
- 0x3300, /* 001100110000 */
- 0x6600, /* 011001100000 */
- 0x6600, /* 011001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0x30, /* 000000110011 */
+ 0x03, 0x30, /* 000000110011 */
+ 0x03, 0x30, /* 000000110011 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x1f, 0xf0, /* 000111111111 */
+ 0x1f, 0xf0, /* 000111111111 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 36 0x24 '$' */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x3fc0, /* 001111111100 */
- 0x66e0, /* 011001101110 */
- 0x6660, /* 011001100110 */
- 0x6600, /* 011001100000 */
- 0x3e00, /* 001111100000 */
- 0x1f80, /* 000111111000 */
- 0x07c0, /* 000001111100 */
- 0x0660, /* 000001100110 */
- 0x0660, /* 000001100110 */
- 0x6660, /* 011001100110 */
- 0x7fc0, /* 011111111100 */
- 0x3f80, /* 001111111000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x66, 0xe0, /* 011001101110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x3e, 0x00, /* 001111100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x07, 0xc0, /* 000001111100 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 37 0x25 '%' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x38c0, /* 001110001100 */
- 0x4cc0, /* 010011001100 */
- 0x4580, /* 010001011000 */
- 0x6580, /* 011001011000 */
- 0x3b00, /* 001110110000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x0dc0, /* 000011011100 */
- 0x1a60, /* 000110100110 */
- 0x1a20, /* 000110100010 */
- 0x3320, /* 001100110010 */
- 0x31c0, /* 001100011100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x38, 0xc0, /* 001110001100 */
+ 0x4c, 0xc0, /* 010011001100 */
+ 0x45, 0x80, /* 010001011000 */
+ 0x65, 0x80, /* 011001011000 */
+ 0x3b, 0x00, /* 001110110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0d, 0xc0, /* 000011011100 */
+ 0x1a, 0x60, /* 000110100110 */
+ 0x1a, 0x20, /* 000110100010 */
+ 0x33, 0x20, /* 001100110010 */
+ 0x31, 0xc0, /* 001100011100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 38 0x26 '&' */
- 0x0000, /* 000000000000 */
- 0x0700, /* 000001110000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x18c0, /* 000110001100 */
- 0x18c0, /* 000110001100 */
- 0x0f80, /* 000011111000 */
- 0x1e00, /* 000111100000 */
- 0x3e00, /* 001111100000 */
- 0x7700, /* 011101110000 */
- 0x6360, /* 011000110110 */
- 0x61e0, /* 011000011110 */
- 0x61c0, /* 011000011100 */
- 0x6180, /* 011000011000 */
- 0x3fe0, /* 001111111110 */
- 0x1e60, /* 000111100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x3e, 0x00, /* 001111100000 */
+ 0x77, 0x00, /* 011101110000 */
+ 0x63, 0x60, /* 011000110110 */
+ 0x61, 0xe0, /* 011000011110 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 39 0x27 ''' */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x1000, /* 000100000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 40 0x28 '(' */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0180, /* 000000011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 41 0x29 ')' */
- 0x0000, /* 000000000000 */
- 0x1800, /* 000110000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 42 0x2a '*' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x0600, /* 000001100000 */
- 0x6660, /* 011001100110 */
- 0x76e0, /* 011101101110 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x76e0, /* 011101101110 */
- 0x6660, /* 011001100110 */
- 0x0600, /* 000001100000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x76, 0xe0, /* 011101101110 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x76, 0xe0, /* 011101101110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 43 0x2b '+' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 44 0x2c ',' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x1000, /* 000100000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 45 0x2d '-' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 46 0x2e '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0c00, /* 000011000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 47 0x2f '/' */
- 0x0000, /* 000000000000 */
- 0x0060, /* 000000000110 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0180, /* 000000011000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x6000, /* 011000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 48 0x30 '0' */
- 0x0000, /* 000000000000 */
- 0x0700, /* 000001110000 */
- 0x0f80, /* 000011111000 */
- 0x1180, /* 000100011000 */
- 0x10c0, /* 000100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x3080, /* 001100001000 */
- 0x1880, /* 000110001000 */
- 0x1f00, /* 000111110000 */
- 0x0e00, /* 000011100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 49 0x31 '1' */
- 0x0000, /* 000000000000 */
- 0x0200, /* 000000100000 */
- 0x0600, /* 000001100000 */
- 0x0e00, /* 000011100000 */
- 0x1e00, /* 000111100000 */
- 0x3600, /* 001101100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x36, 0x00, /* 001101100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 50 0x32 '2' */
- 0x0000, /* 000000000000 */
- 0x1f00, /* 000111110000 */
- 0x3f80, /* 001111111000 */
- 0x61c0, /* 011000011100 */
- 0x40c0, /* 010000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x3020, /* 001100000010 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x40, 0xc0, /* 010000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 51 0x33 '3' */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x1fc0, /* 000111111100 */
- 0x20e0, /* 001000001110 */
- 0x4060, /* 010000000110 */
- 0x0060, /* 000000000110 */
- 0x00e0, /* 000000001110 */
- 0x07c0, /* 000001111100 */
- 0x0fc0, /* 000011111100 */
- 0x00e0, /* 000000001110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x4060, /* 010000000110 */
- 0x6040, /* 011000000100 */
- 0x3f80, /* 001111111000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x07, 0xc0, /* 000001111100 */
+ 0x0f, 0xc0, /* 000011111100 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0x60, 0x40, /* 011000000100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 52 0x34 '4' */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0380, /* 000000111000 */
- 0x0380, /* 000000111000 */
- 0x0580, /* 000001011000 */
- 0x0580, /* 000001011000 */
- 0x0980, /* 000010011000 */
- 0x0980, /* 000010011000 */
- 0x1180, /* 000100011000 */
- 0x1180, /* 000100011000 */
- 0x2180, /* 001000011000 */
- 0x3fe0, /* 001111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0180, /* 000000011000 */
- 0x0180, /* 000000011000 */
- 0x0180, /* 000000011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x05, 0x80, /* 000001011000 */
+ 0x05, 0x80, /* 000001011000 */
+ 0x09, 0x80, /* 000010011000 */
+ 0x09, 0x80, /* 000010011000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x21, 0x80, /* 001000011000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 53 0x35 '5' */
- 0x0000, /* 000000000000 */
- 0x0fc0, /* 000011111100 */
- 0x0fc0, /* 000011111100 */
- 0x1000, /* 000100000000 */
- 0x1000, /* 000100000000 */
- 0x2000, /* 001000000000 */
- 0x3f80, /* 001111111000 */
- 0x31c0, /* 001100011100 */
- 0x00e0, /* 000000001110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x4060, /* 010000000110 */
- 0x6060, /* 011000000110 */
- 0x30c0, /* 001100001100 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xc0, /* 000011111100 */
+ 0x0f, 0xc0, /* 000011111100 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x31, 0xc0, /* 001100011100 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 54 0x36 '6' */
- 0x0000, /* 000000000000 */
- 0x0700, /* 000001110000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x6000, /* 011000000000 */
- 0x6780, /* 011001111000 */
- 0x6fc0, /* 011011111100 */
- 0x70e0, /* 011100001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7040, /* 011100000100 */
- 0x3f80, /* 001111111000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x67, 0x80, /* 011001111000 */
+ 0x6f, 0xc0, /* 011011111100 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 55 0x37 '7' */
- 0x0000, /* 000000000000 */
- 0x1fe0, /* 000111111110 */
- 0x3fe0, /* 001111111110 */
- 0x6040, /* 011000000100 */
- 0x0040, /* 000000000100 */
- 0x00c0, /* 000000001100 */
- 0x0080, /* 000000001000 */
- 0x0080, /* 000000001000 */
- 0x0180, /* 000000011000 */
- 0x0100, /* 000000010000 */
- 0x0100, /* 000000010000 */
- 0x0300, /* 000000110000 */
- 0x0200, /* 000000100000 */
- 0x0200, /* 000000100000 */
- 0x0600, /* 000001100000 */
- 0x0400, /* 000001000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x60, 0x40, /* 011000000100 */
+ 0x00, 0x40, /* 000000000100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0x80, /* 000000001000 */
+ 0x00, 0x80, /* 000000001000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x00, /* 000000010000 */
+ 0x01, 0x00, /* 000000010000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 56 0x38 '8' */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x1180, /* 000100011000 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x1880, /* 000110001000 */
- 0x0d00, /* 000011010000 */
- 0x0600, /* 000001100000 */
- 0x0b00, /* 000010110000 */
- 0x1180, /* 000100011000 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x1880, /* 000110001000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 57 0x39 '9' */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x70e0, /* 011100001110 */
- 0x3f60, /* 001111110110 */
- 0x1e60, /* 000111100110 */
- 0x0060, /* 000000000110 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0180, /* 000000011000 */
- 0x0700, /* 000001110000 */
- 0x3c00, /* 001111000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x3f, 0x60, /* 001111110110 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x3c, 0x00, /* 001111000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 58 0x3a ':' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0c00, /* 000011000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0c00, /* 000011000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 59 0x3b ';' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0c00, /* 000011000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x1000, /* 000100000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 60 0x3c '<' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0060, /* 000000000110 */
- 0x01c0, /* 000000011100 */
- 0x0700, /* 000001110000 */
- 0x1c00, /* 000111000000 */
- 0x7000, /* 011100000000 */
- 0x7000, /* 011100000000 */
- 0x1c00, /* 000111000000 */
- 0x0700, /* 000001110000 */
- 0x01c0, /* 000000011100 */
- 0x0060, /* 000000000110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 61 0x3d '=' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 62 0x3e '>' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x6000, /* 011000000000 */
- 0x3800, /* 001110000000 */
- 0x0e00, /* 000011100000 */
- 0x0380, /* 000000111000 */
- 0x00e0, /* 000000001110 */
- 0x00e0, /* 000000001110 */
- 0x0380, /* 000000111000 */
- 0x0e00, /* 000011100000 */
- 0x3800, /* 001110000000 */
- 0x6000, /* 011000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 63 0x3f '?' */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x1f80, /* 000111111000 */
- 0x39c0, /* 001110011100 */
- 0x20c0, /* 001000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 64 0x40 '@' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x3fc0, /* 001111111100 */
- 0x3060, /* 001100000110 */
- 0x6060, /* 011000000110 */
- 0x6720, /* 011001110010 */
- 0x6fa0, /* 011011111010 */
- 0x6ca0, /* 011011001010 */
- 0x6ca0, /* 011011001010 */
- 0x67e0, /* 011001111110 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x3fe0, /* 001111111110 */
- 0x0fe0, /* 000011111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x67, 0x20, /* 011001110010 */
+ 0x6f, 0xa0, /* 011011111010 */
+ 0x6c, 0xa0, /* 011011001010 */
+ 0x6c, 0xa0, /* 011011001010 */
+ 0x67, 0xe0, /* 011001111110 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 65 0x41 'A' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0b00, /* 000010110000 */
- 0x0b00, /* 000010110000 */
- 0x0900, /* 000010010000 */
- 0x1180, /* 000100011000 */
- 0x1180, /* 000100011000 */
- 0x1080, /* 000100001000 */
- 0x3fc0, /* 001111111100 */
- 0x20c0, /* 001000001100 */
- 0x2040, /* 001000000100 */
- 0x4060, /* 010000000110 */
- 0x4060, /* 010000000110 */
- 0xe0f0, /* 111000001111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x09, 0x00, /* 000010010000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x10, 0x80, /* 000100001000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x20, 0x40, /* 001000000100 */
+ 0x40, 0x60, /* 010000000110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0xe0, 0xf0, /* 111000001111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 66 0x42 'B' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xff00, /* 111111110000 */
- 0x6080, /* 011000001000 */
- 0x60c0, /* 011000001100 */
- 0x60c0, /* 011000001100 */
- 0x60c0, /* 011000001100 */
- 0x6180, /* 011000011000 */
- 0x7f80, /* 011111111000 */
- 0x60c0, /* 011000001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x60c0, /* 011000001100 */
- 0xff80, /* 111111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0x00, /* 111111110000 */
+ 0x60, 0x80, /* 011000001000 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x7f, 0x80, /* 011111111000 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0xff, 0x80, /* 111111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 67 0x43 'C' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0fc0, /* 000011111100 */
- 0x1060, /* 000100000110 */
- 0x2020, /* 001000000010 */
- 0x2000, /* 001000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x2000, /* 001000000000 */
- 0x3020, /* 001100000010 */
- 0x1840, /* 000110000100 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xc0, /* 000011111100 */
+ 0x10, 0x60, /* 000100000110 */
+ 0x20, 0x20, /* 001000000010 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x18, 0x40, /* 000110000100 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 68 0x44 'D' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xff00, /* 111111110000 */
- 0x61c0, /* 011000011100 */
- 0x60c0, /* 011000001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6040, /* 011000000100 */
- 0x6180, /* 011000011000 */
- 0xfe00, /* 111111100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0x00, /* 111111110000 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x40, /* 011000000100 */
+ 0x61, 0x80, /* 011000011000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 69 0x45 'E' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fc0, /* 011111111100 */
- 0x3040, /* 001100000100 */
- 0x3040, /* 001100000100 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3080, /* 001100001000 */
- 0x3f80, /* 001111111000 */
- 0x3080, /* 001100001000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3020, /* 001100000010 */
- 0x3020, /* 001100000010 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 70 0x46 'F' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fc0, /* 011111111100 */
- 0x3040, /* 001100000100 */
- 0x3040, /* 001100000100 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3080, /* 001100001000 */
- 0x3f80, /* 001111111000 */
- 0x3080, /* 001100001000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x7800, /* 011110000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 71 0x47 'G' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0fc0, /* 000011111100 */
- 0x1060, /* 000100000110 */
- 0x2020, /* 001000000010 */
- 0x2000, /* 001000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x61f0, /* 011000011111 */
- 0x6060, /* 011000000110 */
- 0x2060, /* 001000000110 */
- 0x3060, /* 001100000110 */
- 0x1860, /* 000110000110 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xc0, /* 000011111100 */
+ 0x10, 0x60, /* 000100000110 */
+ 0x20, 0x20, /* 001000000010 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x61, 0xf0, /* 011000011111 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x20, 0x60, /* 001000000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 72 0x48 'H' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf0f0, /* 111100001111 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7fe0, /* 011111111110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0xf0f0, /* 111100001111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 73 0x49 'I' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f80, /* 000111111000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 74 0x4a 'J' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f80, /* 000111111000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0400, /* 000001000000 */
- 0x3800, /* 001110000000 */
- 0x3000, /* 001100000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 75 0x4b 'K' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf0e0, /* 111100001110 */
- 0x6180, /* 011000011000 */
- 0x6300, /* 011000110000 */
- 0x6600, /* 011001100000 */
- 0x6c00, /* 011011000000 */
- 0x7800, /* 011110000000 */
- 0x7800, /* 011110000000 */
- 0x7c00, /* 011111000000 */
- 0x6e00, /* 011011100000 */
- 0x6700, /* 011001110000 */
- 0x6380, /* 011000111000 */
- 0x61c0, /* 011000011100 */
- 0x60e0, /* 011000001110 */
- 0xf070, /* 111100000111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0xe0, /* 111100001110 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x63, 0x00, /* 011000110000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x6c, 0x00, /* 011011000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x6e, 0x00, /* 011011100000 */
+ 0x67, 0x00, /* 011001110000 */
+ 0x63, 0x80, /* 011000111000 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x60, 0xe0, /* 011000001110 */
+ 0xf0, 0x70, /* 111100000111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 76 0x4c 'L' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7800, /* 011110000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3020, /* 001100000010 */
- 0x3020, /* 001100000010 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 77 0x4d 'M' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xe070, /* 111000000111 */
- 0x60e0, /* 011000001110 */
- 0x70e0, /* 011100001110 */
- 0x70e0, /* 011100001110 */
- 0x70e0, /* 011100001110 */
- 0x5960, /* 010110010110 */
- 0x5960, /* 010110010110 */
- 0x5960, /* 010110010110 */
- 0x4d60, /* 010011010110 */
- 0x4e60, /* 010011100110 */
- 0x4e60, /* 010011100110 */
- 0x4460, /* 010001000110 */
- 0x4460, /* 010001000110 */
- 0xe4f0, /* 111001001111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xe0, 0x70, /* 111000000111 */
+ 0x60, 0xe0, /* 011000001110 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x59, 0x60, /* 010110010110 */
+ 0x59, 0x60, /* 010110010110 */
+ 0x59, 0x60, /* 010110010110 */
+ 0x4d, 0x60, /* 010011010110 */
+ 0x4e, 0x60, /* 010011100110 */
+ 0x4e, 0x60, /* 010011100110 */
+ 0x44, 0x60, /* 010001000110 */
+ 0x44, 0x60, /* 010001000110 */
+ 0xe4, 0xf0, /* 111001001111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 78 0x4e 'N' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xc070, /* 110000000111 */
- 0x6020, /* 011000000010 */
- 0x7020, /* 011100000010 */
- 0x7820, /* 011110000010 */
- 0x5820, /* 010110000010 */
- 0x4c20, /* 010011000010 */
- 0x4620, /* 010001100010 */
- 0x4720, /* 010001110010 */
- 0x4320, /* 010000110010 */
- 0x41a0, /* 010000011010 */
- 0x40e0, /* 010000001110 */
- 0x40e0, /* 010000001110 */
- 0x4060, /* 010000000110 */
- 0xe030, /* 111000000011 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xc0, 0x70, /* 110000000111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x70, 0x20, /* 011100000010 */
+ 0x78, 0x20, /* 011110000010 */
+ 0x58, 0x20, /* 010110000010 */
+ 0x4c, 0x20, /* 010011000010 */
+ 0x46, 0x20, /* 010001100010 */
+ 0x47, 0x20, /* 010001110010 */
+ 0x43, 0x20, /* 010000110010 */
+ 0x41, 0xa0, /* 010000011010 */
+ 0x40, 0xe0, /* 010000001110 */
+ 0x40, 0xe0, /* 010000001110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0xe0, 0x30, /* 111000000011 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 79 0x4f 'O' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x11c0, /* 000100011100 */
- 0x20c0, /* 001000001100 */
- 0x2060, /* 001000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x2040, /* 001000000100 */
- 0x3040, /* 001100000100 */
- 0x1880, /* 000110001000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x20, 0x60, /* 001000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x20, 0x40, /* 001000000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 80 0x50 'P' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7f80, /* 011111111000 */
- 0x30c0, /* 001100001100 */
- 0x3060, /* 001100000110 */
- 0x3060, /* 001100000110 */
- 0x3060, /* 001100000110 */
- 0x30c0, /* 001100001100 */
- 0x3780, /* 001101111000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x7800, /* 011110000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0x80, /* 011111111000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x37, 0x80, /* 001101111000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 81 0x51 'Q' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x11c0, /* 000100011100 */
- 0x20c0, /* 001000001100 */
- 0x2060, /* 001000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x3040, /* 001100000100 */
- 0x3840, /* 001110000100 */
- 0x1f80, /* 000111111000 */
- 0x0e00, /* 000011100000 */
- 0x1f00, /* 000111110000 */
- 0x2390, /* 001000111001 */
- 0x01e0, /* 000000011110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x20, 0x60, /* 001000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x38, 0x40, /* 001110000100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x23, 0x90, /* 001000111001 */
+ 0x01, 0xe0, /* 000000011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 82 0x52 'R' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xff00, /* 111111110000 */
- 0x6180, /* 011000011000 */
- 0x60c0, /* 011000001100 */
- 0x60c0, /* 011000001100 */
- 0x60c0, /* 011000001100 */
- 0x6080, /* 011000001000 */
- 0x7f00, /* 011111110000 */
- 0x7c00, /* 011111000000 */
- 0x6e00, /* 011011100000 */
- 0x6700, /* 011001110000 */
- 0x6380, /* 011000111000 */
- 0x61c0, /* 011000011100 */
- 0x60e0, /* 011000001110 */
- 0xf070, /* 111100000111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0x00, /* 111111110000 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0x80, /* 011000001000 */
+ 0x7f, 0x00, /* 011111110000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x6e, 0x00, /* 011011100000 */
+ 0x67, 0x00, /* 011001110000 */
+ 0x63, 0x80, /* 011000111000 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x60, 0xe0, /* 011000001110 */
+ 0xf0, 0x70, /* 111100000111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 83 0x53 'S' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1fe0, /* 000111111110 */
- 0x3060, /* 001100000110 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x7000, /* 011100000000 */
- 0x3c00, /* 001111000000 */
- 0x1e00, /* 000111100000 */
- 0x0780, /* 000001111000 */
- 0x01c0, /* 000000011100 */
- 0x00e0, /* 000000001110 */
- 0x4060, /* 010000000110 */
- 0x4060, /* 010000000110 */
- 0x60c0, /* 011000001100 */
- 0x7f80, /* 011111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x3c, 0x00, /* 001111000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x7f, 0x80, /* 011111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 84 0x54 'T' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x4620, /* 010001100010 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x46, 0x20, /* 010001100010 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 85 0x55 'U' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf070, /* 111100000111 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x7040, /* 011100000100 */
- 0x3fc0, /* 001111111100 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0x70, /* 111100000111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 86 0x56 'V' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xe0e0, /* 111000001110 */
- 0x6040, /* 011000000100 */
- 0x3080, /* 001100001000 */
- 0x3080, /* 001100001000 */
- 0x3080, /* 001100001000 */
- 0x1900, /* 000110010000 */
- 0x1900, /* 000110010000 */
- 0x1900, /* 000110010000 */
- 0x0a00, /* 000010100000 */
- 0x0e00, /* 000011100000 */
- 0x0e00, /* 000011100000 */
- 0x0400, /* 000001000000 */
- 0x0400, /* 000001000000 */
- 0x0400, /* 000001000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xe0, 0xe0, /* 111000001110 */
+ 0x60, 0x40, /* 011000000100 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x19, 0x00, /* 000110010000 */
+ 0x19, 0x00, /* 000110010000 */
+ 0x19, 0x00, /* 000110010000 */
+ 0x0a, 0x00, /* 000010100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 87 0x57 'W' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfef0, /* 111111101111 */
- 0x6620, /* 011001100010 */
- 0x6620, /* 011001100010 */
- 0x6620, /* 011001100010 */
- 0x7620, /* 011101100010 */
- 0x7740, /* 011101110100 */
- 0x3340, /* 001100110100 */
- 0x3740, /* 001101110100 */
- 0x3bc0, /* 001110111100 */
- 0x3b80, /* 001110111000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xfe, 0xf0, /* 111111101111 */
+ 0x66, 0x20, /* 011001100010 */
+ 0x66, 0x20, /* 011001100010 */
+ 0x66, 0x20, /* 011001100010 */
+ 0x76, 0x20, /* 011101100010 */
+ 0x77, 0x40, /* 011101110100 */
+ 0x33, 0x40, /* 001100110100 */
+ 0x37, 0x40, /* 001101110100 */
+ 0x3b, 0xc0, /* 001110111100 */
+ 0x3b, 0x80, /* 001110111000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 88 0x58 'X' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf070, /* 111100000111 */
- 0x6020, /* 011000000010 */
- 0x3040, /* 001100000100 */
- 0x3880, /* 001110001000 */
- 0x1880, /* 000110001000 */
- 0x0d00, /* 000011010000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0b00, /* 000010110000 */
- 0x1180, /* 000100011000 */
- 0x11c0, /* 000100011100 */
- 0x20c0, /* 001000001100 */
- 0x4060, /* 010000000110 */
- 0xe0f0, /* 111000001111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0x70, /* 111100000111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x40, 0x60, /* 010000000110 */
+ 0xe0, 0xf0, /* 111000001111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 89 0x59 'Y' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf070, /* 111100000111 */
- 0x6020, /* 011000000010 */
- 0x3040, /* 001100000100 */
- 0x1880, /* 000110001000 */
- 0x1880, /* 000110001000 */
- 0x0d00, /* 000011010000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0x70, /* 111100000111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 90 0x5a 'Z' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fe0, /* 001111111110 */
- 0x20c0, /* 001000001100 */
- 0x00c0, /* 000000001100 */
- 0x0180, /* 000000011000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x1820, /* 000110000010 */
- 0x3fe0, /* 001111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x20, /* 000110000010 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 91 0x5b '[' */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x0f80, /* 000011111000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0f80, /* 000011111000 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 92 0x5c '\' */
- 0x0000, /* 000000000000 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0180, /* 000000011000 */
- 0x0180, /* 000000011000 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0060, /* 000000000110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 93 0x5d ']' */
- 0x0000, /* 000000000000 */
- 0x1f00, /* 000111110000 */
- 0x1f00, /* 000111110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x1f00, /* 000111110000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 94 0x5e '^' */
- 0x0000, /* 000000000000 */
- 0x0400, /* 000001000000 */
- 0x0e00, /* 000011100000 */
- 0x1b00, /* 000110110000 */
- 0x3180, /* 001100011000 */
- 0x60c0, /* 011000001100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1b, 0x00, /* 000110110000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 95 0x5f '_' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 96 0x60 '`' */
- 0x0000, /* 000000000000 */
- 0x0100, /* 000000010000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0780, /* 000001111000 */
- 0x0780, /* 000001111000 */
- 0x0300, /* 000000110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x00, /* 000000010000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 97 0x61 'a' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x10c0, /* 000100001100 */
- 0x03c0, /* 000000111100 */
- 0x1cc0, /* 000111001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1ee0, /* 000111101110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0xe0, /* 000111101110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 98 0x62 'b' */
- 0x0000, /* 000000000000 */
- 0x2000, /* 001000000000 */
- 0x6000, /* 011000000000 */
- 0xe000, /* 111000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6780, /* 011001111000 */
- 0x6fc0, /* 011011111100 */
- 0x70e0, /* 011100001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7060, /* 011100000110 */
- 0x78c0, /* 011110001100 */
- 0x4f80, /* 010011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0xe0, 0x00, /* 111000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x67, 0x80, /* 011001111000 */
+ 0x6f, 0xc0, /* 011011111100 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x60, /* 011100000110 */
+ 0x78, 0xc0, /* 011110001100 */
+ 0x4f, 0x80, /* 010011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 99 0x63 'c' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f80, /* 000111111000 */
- 0x31c0, /* 001100011100 */
- 0x20c0, /* 001000001100 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x7040, /* 011100000100 */
- 0x30c0, /* 001100001100 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x31, 0xc0, /* 001100011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 100 0x64 'd' */
- 0x0000, /* 000000000000 */
- 0x0060, /* 000000000110 */
- 0x00e0, /* 000000001110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x0f60, /* 000011110110 */
- 0x31e0, /* 001100011110 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x70e0, /* 011100001110 */
- 0x3960, /* 001110010110 */
- 0x1e70, /* 000111100111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x0f, 0x60, /* 000011110110 */
+ 0x31, 0xe0, /* 001100011110 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0xe0, /* 011100001110 */
+ 0x39, 0x60, /* 001110010110 */
+ 0x1e, 0x70, /* 000111100111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 101 0x65 'e' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x30c0, /* 001100001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7fe0, /* 011111111110 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x1860, /* 000110000110 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 102 0x66 'f' */
- 0x0000, /* 000000000000 */
- 0x0380, /* 000000111000 */
- 0x04c0, /* 000001001100 */
- 0x04c0, /* 000001001100 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x3f80, /* 001111111000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x1e00, /* 000111100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x04, 0xc0, /* 000001001100 */
+ 0x04, 0xc0, /* 000001001100 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 103 0x67 'g' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f20, /* 000111110010 */
- 0x31e0, /* 001100011110 */
- 0x60c0, /* 011000001100 */
- 0x60c0, /* 011000001100 */
- 0x60c0, /* 011000001100 */
- 0x3180, /* 001100011000 */
- 0x3f00, /* 001111110000 */
- 0x6000, /* 011000000000 */
- 0x7fc0, /* 011111111100 */
- 0x3fe0, /* 001111111110 */
- 0x2060, /* 001000000110 */
- 0x4020, /* 010000000010 */
- 0x4020, /* 010000000010 */
- 0x7fc0, /* 011111111100 */
- 0x3f80, /* 001111111000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x20, /* 000111110010 */
+ 0x31, 0xe0, /* 001100011110 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x3f, 0x00, /* 001111110000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x20, 0x60, /* 001000000110 */
+ 0x40, 0x20, /* 010000000010 */
+ 0x40, 0x20, /* 010000000010 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x00, 0x00, /* 000000000000 */
/* 104 0x68 'h' */
- 0x0000, /* 000000000000 */
- 0x1000, /* 000100000000 */
- 0x3000, /* 001100000000 */
- 0x7000, /* 011100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3780, /* 001101111000 */
- 0x39c0, /* 001110011100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x79e0, /* 011110011110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x37, 0x80, /* 001101111000 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 105 0x69 'i' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 106 0x6a 'j' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x03c0, /* 000000111100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x20c0, /* 001000001100 */
- 0x30c0, /* 001100001100 */
- 0x3880, /* 001110001000 */
- 0x1f00, /* 000111110000 */
- 0x0e00, /* 000011100000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x00, 0x00, /* 000000000000 */
/* 107 0x6b 'k' */
- 0x0000, /* 000000000000 */
- 0x6000, /* 011000000000 */
- 0xe000, /* 111000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x61c0, /* 011000011100 */
- 0x6300, /* 011000110000 */
- 0x6600, /* 011001100000 */
- 0x7c00, /* 011111000000 */
- 0x7800, /* 011110000000 */
- 0x7c00, /* 011111000000 */
- 0x6e00, /* 011011100000 */
- 0x6700, /* 011001110000 */
- 0x6380, /* 011000111000 */
- 0xf1e0, /* 111100011110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0xe0, 0x00, /* 111000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x63, 0x00, /* 011000110000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x6e, 0x00, /* 011011100000 */
+ 0x67, 0x00, /* 011001110000 */
+ 0x63, 0x80, /* 011000111000 */
+ 0xf1, 0xe0, /* 111100011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 108 0x6c 'l' */
- 0x0000, /* 000000000000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 109 0x6d 'm' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xddc0, /* 110111011100 */
- 0x6ee0, /* 011011101110 */
- 0x6660, /* 011001100110 */
- 0x6660, /* 011001100110 */
- 0x6660, /* 011001100110 */
- 0x6660, /* 011001100110 */
- 0x6660, /* 011001100110 */
- 0x6660, /* 011001100110 */
- 0x6660, /* 011001100110 */
- 0xef70, /* 111011110111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xdd, 0xc0, /* 110111011100 */
+ 0x6e, 0xe0, /* 011011101110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0xef, 0x70, /* 111011110111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 110 0x6e 'n' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x2780, /* 001001111000 */
- 0x79c0, /* 011110011100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x79e0, /* 011110011110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x27, 0x80, /* 001001111000 */
+ 0x79, 0xc0, /* 011110011100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 111 0x6f 'o' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7040, /* 011100000100 */
- 0x3880, /* 001110001000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 112 0x70 'p' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xef80, /* 111011111000 */
- 0x71c0, /* 011100011100 */
- 0x60e0, /* 011000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6040, /* 011000000100 */
- 0x7080, /* 011100001000 */
- 0x7f00, /* 011111110000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0xf000, /* 111100000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xef, 0x80, /* 111011111000 */
+ 0x71, 0xc0, /* 011100011100 */
+ 0x60, 0xe0, /* 011000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x40, /* 011000000100 */
+ 0x70, 0x80, /* 011100001000 */
+ 0x7f, 0x00, /* 011111110000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0xf0, 0x00, /* 111100000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 113 0x71 'q' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f20, /* 000011110010 */
- 0x11e0, /* 000100011110 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7060, /* 011100000110 */
- 0x38e0, /* 001110001110 */
- 0x1fe0, /* 000111111110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x0060, /* 000000000110 */
- 0x00f0, /* 000000001111 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x20, /* 000011110010 */
+ 0x11, 0xe0, /* 000100011110 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x60, /* 011100000110 */
+ 0x38, 0xe0, /* 001110001110 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0xf0, /* 000000001111 */
+ 0x00, 0x00, /* 000000000000 */
/* 114 0x72 'r' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7380, /* 011100111000 */
- 0x34c0, /* 001101001100 */
- 0x38c0, /* 001110001100 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x7800, /* 011110000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x73, 0x80, /* 011100111000 */
+ 0x34, 0xc0, /* 001101001100 */
+ 0x38, 0xc0, /* 001110001100 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 115 0x73 's' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1fc0, /* 000111111100 */
- 0x30c0, /* 001100001100 */
- 0x3040, /* 001100000100 */
- 0x3800, /* 001110000000 */
- 0x1e00, /* 000111100000 */
- 0x0780, /* 000001111000 */
- 0x01c0, /* 000000011100 */
- 0x20c0, /* 001000001100 */
- 0x30c0, /* 001100001100 */
- 0x3f80, /* 001111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 116 0x74 't' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0400, /* 000001000000 */
- 0x0400, /* 000001000000 */
- 0x0c00, /* 000011000000 */
- 0x7fc0, /* 011111111100 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c00, /* 000011000000 */
- 0x0c20, /* 000011000010 */
- 0x0e40, /* 000011100100 */
- 0x0780, /* 000001111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x20, /* 000011000010 */
+ 0x0e, 0x40, /* 000011100100 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 117 0x75 'u' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x79e0, /* 011110011110 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1e60, /* 000111100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 118 0x76 'v' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf070, /* 111100000111 */
- 0x6020, /* 011000000010 */
- 0x3040, /* 001100000100 */
- 0x3040, /* 001100000100 */
- 0x1880, /* 000110001000 */
- 0x1880, /* 000110001000 */
- 0x0d00, /* 000011010000 */
- 0x0d00, /* 000011010000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0x70, /* 111100000111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 119 0x77 'w' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xff70, /* 111111110111 */
- 0x6620, /* 011001100010 */
- 0x6620, /* 011001100010 */
- 0x6620, /* 011001100010 */
- 0x3740, /* 001101110100 */
- 0x3b40, /* 001110110100 */
- 0x3b40, /* 001110110100 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0x70, /* 111111110111 */
+ 0x66, 0x20, /* 011001100010 */
+ 0x66, 0x20, /* 011001100010 */
+ 0x66, 0x20, /* 011001100010 */
+ 0x37, 0x40, /* 001101110100 */
+ 0x3b, 0x40, /* 001110110100 */
+ 0x3b, 0x40, /* 001110110100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 120 0x78 'x' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf8f0, /* 111110001111 */
- 0x7040, /* 011100000100 */
- 0x3880, /* 001110001000 */
- 0x1d00, /* 000111010000 */
- 0x0e00, /* 000011100000 */
- 0x0700, /* 000001110000 */
- 0x0b80, /* 000010111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0xf1f0, /* 111100011111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf8, 0xf0, /* 111110001111 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1d, 0x00, /* 000111010000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0b, 0x80, /* 000010111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0xf1, 0xf0, /* 111100011111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 121 0x79 'y' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf0f0, /* 111100001111 */
- 0x6020, /* 011000000010 */
- 0x3040, /* 001100000100 */
- 0x3040, /* 001100000100 */
- 0x1880, /* 000110001000 */
- 0x1880, /* 000110001000 */
- 0x0d00, /* 000011010000 */
- 0x0d00, /* 000011010000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0400, /* 000001000000 */
- 0x0c00, /* 000011000000 */
- 0x0800, /* 000010000000 */
- 0x7800, /* 011110000000 */
- 0x7000, /* 011100000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x08, 0x00, /* 000010000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 122 0x7a 'z' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x60e0, /* 011000001110 */
- 0x41c0, /* 010000011100 */
- 0x0380, /* 000000111000 */
- 0x0700, /* 000001110000 */
- 0x0e00, /* 000011100000 */
- 0x1c00, /* 000111000000 */
- 0x3820, /* 001110000010 */
- 0x7060, /* 011100000110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0xe0, /* 011000001110 */
+ 0x41, 0xc0, /* 010000011100 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x38, 0x20, /* 001110000010 */
+ 0x70, 0x60, /* 011100000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 123 0x7b '{' */
- 0x0000, /* 000000000000 */
- 0x0380, /* 000000111000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x3800, /* 001110000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0380, /* 000000111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 124 0x7c '|' */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
/* 125 0x7d '}' */
- 0x0000, /* 000000000000 */
- 0x1c00, /* 000111000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x01c0, /* 000000011100 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1c00, /* 000111000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 126 0x7e '~' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1c20, /* 000111000010 */
- 0x3e60, /* 001111100110 */
- 0x67c0, /* 011001111100 */
- 0x4380, /* 010000111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1c, 0x20, /* 000111000010 */
+ 0x3e, 0x60, /* 001111100110 */
+ 0x67, 0xc0, /* 011001111100 */
+ 0x43, 0x80, /* 010000111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 127 0x7f '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 128 0x80 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0fc0, /* 000011111100 */
- 0x1060, /* 000100000110 */
- 0x2020, /* 001000000010 */
- 0x2000, /* 001000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x2000, /* 001000000000 */
- 0x3020, /* 001100000010 */
- 0x1840, /* 000110000100 */
- 0x0f80, /* 000011111000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0180, /* 000000011000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xc0, /* 000011111100 */
+ 0x10, 0x60, /* 000100000110 */
+ 0x20, 0x20, /* 001000000010 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x20, 0x00, /* 001000000000 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x18, 0x40, /* 000110000100 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 129 0x81 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x79e0, /* 011110011110 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1e60, /* 000111100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 130 0x82 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x30c0, /* 001100001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7fe0, /* 011111111110 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x1860, /* 000110000110 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 131 0x83 '.' */
- 0x0000, /* 000000000000 */
- 0x0200, /* 000000100000 */
- 0x0700, /* 000001110000 */
- 0x0d80, /* 000011011000 */
- 0x18c0, /* 000110001100 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x10c0, /* 000100001100 */
- 0x03c0, /* 000000111100 */
- 0x1cc0, /* 000111001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1ee0, /* 000111101110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0xe0, /* 000111101110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 132 0x84 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x10c0, /* 000100001100 */
- 0x03c0, /* 000000111100 */
- 0x1cc0, /* 000111001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1ee0, /* 000111101110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0xe0, /* 000111101110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 133 0x85 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x10c0, /* 000100001100 */
- 0x03c0, /* 000000111100 */
- 0x1cc0, /* 000111001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1ee0, /* 000111101110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0xe0, /* 000111101110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 134 0x86 '.' */
- 0x0000, /* 000000000000 */
- 0x0700, /* 000001110000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0700, /* 000001110000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x10c0, /* 000100001100 */
- 0x03c0, /* 000000111100 */
- 0x1cc0, /* 000111001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1ee0, /* 000111101110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0xe0, /* 000111101110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 135 0x87 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f80, /* 000111111000 */
- 0x31c0, /* 001100011100 */
- 0x20c0, /* 001000001100 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x7040, /* 011100000100 */
- 0x30c0, /* 001100001100 */
- 0x1f80, /* 000111111000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0180, /* 000000011000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x31, 0xc0, /* 001100011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 136 0x88 '.' */
- 0x0000, /* 000000000000 */
- 0x0200, /* 000000100000 */
- 0x0700, /* 000001110000 */
- 0x0d80, /* 000011011000 */
- 0x18c0, /* 000110001100 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x30c0, /* 001100001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7fe0, /* 011111111110 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x1860, /* 000110000110 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 137 0x89 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x30c0, /* 001100001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7fe0, /* 011111111110 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x1860, /* 000110000110 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 138 0x8a '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x30c0, /* 001100001100 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7fe0, /* 011111111110 */
- 0x6000, /* 011000000000 */
- 0x6000, /* 011000000000 */
- 0x3000, /* 001100000000 */
- 0x1860, /* 000110000110 */
- 0x0f80, /* 000011111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 139 0x8b '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 140 0x8c '.' */
- 0x0000, /* 000000000000 */
- 0x0400, /* 000001000000 */
- 0x0e00, /* 000011100000 */
- 0x1b00, /* 000110110000 */
- 0x3180, /* 001100011000 */
- 0x0000, /* 000000000000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1b, 0x00, /* 000110110000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 141 0x8d '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1800, /* 000110000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 142 0x8e '.' */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0400, /* 000001000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0b00, /* 000010110000 */
- 0x0b00, /* 000010110000 */
- 0x1980, /* 000110011000 */
- 0x1180, /* 000100011000 */
- 0x3fc0, /* 001111111100 */
- 0x20c0, /* 001000001100 */
- 0x6060, /* 011000000110 */
- 0x4060, /* 010000000110 */
- 0xe0f0, /* 111000001111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0xe0, 0xf0, /* 111000001111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 143 0x8f '.' */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x1980, /* 000110011000 */
- 0x0f00, /* 000011110000 */
- 0x0400, /* 000001000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0b00, /* 000010110000 */
- 0x0b00, /* 000010110000 */
- 0x1980, /* 000110011000 */
- 0x1180, /* 000100011000 */
- 0x3fc0, /* 001111111100 */
- 0x20c0, /* 001000001100 */
- 0x6060, /* 011000000110 */
- 0x4060, /* 010000000110 */
- 0xe0f0, /* 111000001111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x11, 0x80, /* 000100011000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0xe0, 0xf0, /* 111000001111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 144 0x90 '.' */
- 0x0000, /* 000000000000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0800, /* 000010000000 */
- 0x7fe0, /* 011111111110 */
- 0x3020, /* 001100000010 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3080, /* 001100001000 */
- 0x3f80, /* 001111111000 */
- 0x3080, /* 001100001000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3020, /* 001100000010 */
- 0x3020, /* 001100000010 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x08, 0x00, /* 000010000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x30, 0x20, /* 001100000010 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 145 0x91 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3de0, /* 001111011110 */
- 0x6630, /* 011001100011 */
- 0x4630, /* 010001100011 */
- 0x0630, /* 000001100011 */
- 0x3ff0, /* 001111111111 */
- 0x6600, /* 011001100000 */
- 0xc600, /* 110001100000 */
- 0xc600, /* 110001100000 */
- 0xe730, /* 111001110011 */
- 0x7de0, /* 011111011110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3d, 0xe0, /* 001111011110 */
+ 0x66, 0x30, /* 011001100011 */
+ 0x46, 0x30, /* 010001100011 */
+ 0x06, 0x30, /* 000001100011 */
+ 0x3f, 0xf0, /* 001111111111 */
+ 0x66, 0x00, /* 011001100000 */
+ 0xc6, 0x00, /* 110001100000 */
+ 0xc6, 0x00, /* 110001100000 */
+ 0xe7, 0x30, /* 111001110011 */
+ 0x7d, 0xe0, /* 011111011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 146 0x92 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x03f0, /* 000000111111 */
- 0x0710, /* 000001110001 */
- 0x0710, /* 000001110001 */
- 0x0b00, /* 000010110000 */
- 0x0b00, /* 000010110000 */
- 0x0b20, /* 000010110010 */
- 0x13e0, /* 000100111110 */
- 0x1320, /* 000100110010 */
- 0x3f00, /* 001111110000 */
- 0x2300, /* 001000110000 */
- 0x2300, /* 001000110000 */
- 0x4310, /* 010000110001 */
- 0x4310, /* 010000110001 */
- 0xe7f0, /* 111001111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x07, 0x10, /* 000001110001 */
+ 0x07, 0x10, /* 000001110001 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x0b, 0x00, /* 000010110000 */
+ 0x0b, 0x20, /* 000010110010 */
+ 0x13, 0xe0, /* 000100111110 */
+ 0x13, 0x20, /* 000100110010 */
+ 0x3f, 0x00, /* 001111110000 */
+ 0x23, 0x00, /* 001000110000 */
+ 0x23, 0x00, /* 001000110000 */
+ 0x43, 0x10, /* 010000110001 */
+ 0x43, 0x10, /* 010000110001 */
+ 0xe7, 0xf0, /* 111001111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 147 0x93 '.' */
- 0x0000, /* 000000000000 */
- 0x0200, /* 000000100000 */
- 0x0700, /* 000001110000 */
- 0x0d80, /* 000011011000 */
- 0x18c0, /* 000110001100 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7040, /* 011100000100 */
- 0x3880, /* 001110001000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 148 0x94 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7040, /* 011100000100 */
- 0x3880, /* 001110001000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 149 0x95 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0300, /* 000000110000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7040, /* 011100000100 */
- 0x3880, /* 001110001000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 150 0x96 '.' */
- 0x0000, /* 000000000000 */
- 0x0200, /* 000000100000 */
- 0x0700, /* 000001110000 */
- 0x0d80, /* 000011011000 */
- 0x18c0, /* 000110001100 */
- 0x0000, /* 000000000000 */
- 0x79e0, /* 011110011110 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1e60, /* 000111100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 151 0x97 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1800, /* 000110000000 */
- 0x0c00, /* 000011000000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x79e0, /* 011110011110 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1e60, /* 000111100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 152 0x98 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xf0f0, /* 111100001111 */
- 0x6020, /* 011000000010 */
- 0x3040, /* 001100000100 */
- 0x3040, /* 001100000100 */
- 0x1880, /* 000110001000 */
- 0x1880, /* 000110001000 */
- 0x0d00, /* 000011010000 */
- 0x0d00, /* 000011010000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0400, /* 000001000000 */
- 0x0c00, /* 000011000000 */
- 0x0800, /* 000010000000 */
- 0x7800, /* 011110000000 */
- 0x7000, /* 011100000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x0d, 0x00, /* 000011010000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x08, 0x00, /* 000010000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 153 0x99 '.' */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20c0, /* 001000001100 */
- 0x2060, /* 001000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x2040, /* 001000000100 */
- 0x3040, /* 001100000100 */
- 0x1880, /* 000110001000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x20, 0x60, /* 001000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x20, 0x40, /* 001000000100 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x18, 0x80, /* 000110001000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 154 0x9a '.' */
- 0x0000, /* 000000000000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0xe030, /* 111000000011 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x6020, /* 011000000010 */
- 0x7040, /* 011100000100 */
- 0x3fc0, /* 001111111100 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0xe0, 0x30, /* 111000000011 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 155 0x9b '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x36c0, /* 001101101100 */
- 0x26c0, /* 001001101100 */
- 0x6600, /* 011001100000 */
- 0x6600, /* 011001100000 */
- 0x6600, /* 011001100000 */
- 0x6600, /* 011001100000 */
- 0x7640, /* 011101100100 */
- 0x36c0, /* 001101101100 */
- 0x1f80, /* 000111111000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x36, 0xc0, /* 001101101100 */
+ 0x26, 0xc0, /* 001001101100 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x76, 0x40, /* 011101100100 */
+ 0x36, 0xc0, /* 001101101100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 156 0x9c '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x1cc0, /* 000111001100 */
- 0x18c0, /* 000110001100 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x7e00, /* 011111100000 */
- 0x7e00, /* 011111100000 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x1800, /* 000110000000 */
- 0x3e20, /* 001111100010 */
- 0x7fe0, /* 011111111110 */
- 0x61c0, /* 011000011100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x7e, 0x00, /* 011111100000 */
+ 0x7e, 0x00, /* 011111100000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x3e, 0x20, /* 001111100010 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x61, 0xc0, /* 011000011100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 157 0x9d '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x30c0, /* 001100001100 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0f00, /* 000011110000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 158 0x9e '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 159 0x9f '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 160 0xa0 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x18c0, /* 000110001100 */
- 0x10c0, /* 000100001100 */
- 0x03c0, /* 000000111100 */
- 0x1cc0, /* 000111001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1ee0, /* 000111101110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x03, 0xc0, /* 000000111100 */
+ 0x1c, 0xc0, /* 000111001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0xe0, /* 000111101110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 161 0xa1 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x1e00, /* 000111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x1f80, /* 000111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 162 0xa2 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0f80, /* 000011111000 */
- 0x11c0, /* 000100011100 */
- 0x20e0, /* 001000001110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x6060, /* 011000000110 */
- 0x7040, /* 011100000100 */
- 0x3880, /* 001110001000 */
- 0x1f00, /* 000111110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 163 0xa3 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0180, /* 000000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x79e0, /* 011110011110 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x1e60, /* 000111100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1e, 0x60, /* 000111100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 164 0xa4 '.' */
- 0x0000, /* 000000000000 */
- 0x1c40, /* 000111000100 */
- 0x3fc0, /* 001111111100 */
- 0x2380, /* 001000111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x2780, /* 001001111000 */
- 0x79c0, /* 011110011100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x79e0, /* 011110011110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1c, 0x40, /* 000111000100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x23, 0x80, /* 001000111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x27, 0x80, /* 001001111000 */
+ 0x79, 0xc0, /* 011110011100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x79, 0xe0, /* 011110011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 165 0xa5 '.' */
- 0x0000, /* 000000000000 */
- 0x1c40, /* 000111000100 */
- 0x3fc0, /* 001111111100 */
- 0x2380, /* 001000111000 */
- 0xc070, /* 110000000111 */
- 0x6020, /* 011000000010 */
- 0x7020, /* 011100000010 */
- 0x7820, /* 011110000010 */
- 0x5c20, /* 010111000010 */
- 0x4e20, /* 010011100010 */
- 0x4720, /* 010001110010 */
- 0x43a0, /* 010000111010 */
- 0x41e0, /* 010000011110 */
- 0x40e0, /* 010000001110 */
- 0x4060, /* 010000000110 */
- 0xe030, /* 111000000011 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1c, 0x40, /* 000111000100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x23, 0x80, /* 001000111000 */
+ 0xc0, 0x70, /* 110000000111 */
+ 0x60, 0x20, /* 011000000010 */
+ 0x70, 0x20, /* 011100000010 */
+ 0x78, 0x20, /* 011110000010 */
+ 0x5c, 0x20, /* 010111000010 */
+ 0x4e, 0x20, /* 010011100010 */
+ 0x47, 0x20, /* 010001110010 */
+ 0x43, 0xa0, /* 010000111010 */
+ 0x41, 0xe0, /* 010000011110 */
+ 0x40, 0xe0, /* 010000001110 */
+ 0x40, 0x60, /* 010000000110 */
+ 0xe0, 0x30, /* 111000000011 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 166 0xa6 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1f00, /* 000111110000 */
- 0x3180, /* 001100011000 */
- 0x0180, /* 000000011000 */
- 0x0780, /* 000001111000 */
- 0x1980, /* 000110011000 */
- 0x3180, /* 001100011000 */
- 0x3180, /* 001100011000 */
- 0x3380, /* 001100111000 */
- 0x1dc0, /* 000111011100 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x33, 0x80, /* 001100111000 */
+ 0x1d, 0xc0, /* 000111011100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 167 0xa7 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0700, /* 000001110000 */
- 0x1980, /* 000110011000 */
- 0x10c0, /* 000100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x3080, /* 001100001000 */
- 0x1980, /* 000110011000 */
- 0x0e00, /* 000011100000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x10, 0xc0, /* 000100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0x80, /* 001100001000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 168 0xa8 '.' */
- 0x0000, /* 000000000000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0300, /* 000000110000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1800, /* 000110000000 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x3040, /* 001100000100 */
- 0x39c0, /* 001110011100 */
- 0x1f80, /* 000111111000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x40, /* 001100000100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 169 0xa9 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 170 0xaa '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x00c0, /* 000000001100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 171 0xab '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1000, /* 000100000000 */
- 0x3000, /* 001100000000 */
- 0x1000, /* 000100000000 */
- 0x1040, /* 000100000100 */
- 0x1080, /* 000100001000 */
- 0x1100, /* 000100010000 */
- 0x3a00, /* 001110100000 */
- 0x05c0, /* 000001011100 */
- 0x0a20, /* 000010100010 */
- 0x1020, /* 000100000010 */
- 0x20c0, /* 001000001100 */
- 0x4100, /* 010000010000 */
- 0x0200, /* 000000100000 */
- 0x03e0, /* 000000111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x10, 0x40, /* 000100000100 */
+ 0x10, 0x80, /* 000100001000 */
+ 0x11, 0x00, /* 000100010000 */
+ 0x3a, 0x00, /* 001110100000 */
+ 0x05, 0xc0, /* 000001011100 */
+ 0x0a, 0x20, /* 000010100010 */
+ 0x10, 0x20, /* 000100000010 */
+ 0x20, 0xc0, /* 001000001100 */
+ 0x41, 0x00, /* 010000010000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x03, 0xe0, /* 000000111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 172 0xac '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x1000, /* 000100000000 */
- 0x3000, /* 001100000000 */
- 0x1000, /* 000100000000 */
- 0x1040, /* 000100000100 */
- 0x1080, /* 000100001000 */
- 0x1100, /* 000100010000 */
- 0x3a40, /* 001110100100 */
- 0x04c0, /* 000001001100 */
- 0x0940, /* 000010010100 */
- 0x1240, /* 000100100100 */
- 0x2440, /* 001001000100 */
- 0x47e0, /* 010001111110 */
- 0x0040, /* 000000000100 */
- 0x0040, /* 000000000100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x10, 0x00, /* 000100000000 */
+ 0x10, 0x40, /* 000100000100 */
+ 0x10, 0x80, /* 000100001000 */
+ 0x11, 0x00, /* 000100010000 */
+ 0x3a, 0x40, /* 001110100100 */
+ 0x04, 0xc0, /* 000001001100 */
+ 0x09, 0x40, /* 000010010100 */
+ 0x12, 0x40, /* 000100100100 */
+ 0x24, 0x40, /* 001001000100 */
+ 0x47, 0xe0, /* 010001111110 */
+ 0x00, 0x40, /* 000000000100 */
+ 0x00, 0x40, /* 000000000100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 173 0xad '.' */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 174 0xae '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0660, /* 000001100110 */
- 0x0cc0, /* 000011001100 */
- 0x1980, /* 000110011000 */
- 0x3300, /* 001100110000 */
- 0x6600, /* 011001100000 */
- 0x3300, /* 001100110000 */
- 0x1980, /* 000110011000 */
- 0x0cc0, /* 000011001100 */
- 0x0660, /* 000001100110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 175 0xaf '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x6600, /* 011001100000 */
- 0x3300, /* 001100110000 */
- 0x1980, /* 000110011000 */
- 0x0cc0, /* 000011001100 */
- 0x0660, /* 000001100110 */
- 0x0cc0, /* 000011001100 */
- 0x1980, /* 000110011000 */
- 0x3300, /* 001100110000 */
- 0x6600, /* 011001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 176 0xb0 '.' */
- 0x0c30, /* 000011000011 */
- 0x0820, /* 000010000010 */
- 0x6180, /* 011000011000 */
- 0x2080, /* 001000001000 */
- 0x0c30, /* 000011000011 */
- 0x0820, /* 000010000010 */
- 0x6180, /* 011000011000 */
- 0x2080, /* 001000001000 */
- 0x0c30, /* 000011000011 */
- 0x0820, /* 000010000010 */
- 0x6180, /* 011000011000 */
- 0x2080, /* 001000001000 */
- 0x0c30, /* 000011000011 */
- 0x0820, /* 000010000010 */
- 0x6180, /* 011000011000 */
- 0x2080, /* 001000001000 */
- 0x0c30, /* 000011000011 */
- 0x0820, /* 000010000010 */
- 0x6180, /* 011000011000 */
- 0x2080, /* 001000001000 */
- 0x0c30, /* 000011000011 */
- 0x0820, /* 000010000010 */
+ 0x0c, 0x30, /* 000011000011 */
+ 0x08, 0x20, /* 000010000010 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x20, 0x80, /* 001000001000 */
+ 0x0c, 0x30, /* 000011000011 */
+ 0x08, 0x20, /* 000010000010 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x20, 0x80, /* 001000001000 */
+ 0x0c, 0x30, /* 000011000011 */
+ 0x08, 0x20, /* 000010000010 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x20, 0x80, /* 001000001000 */
+ 0x0c, 0x30, /* 000011000011 */
+ 0x08, 0x20, /* 000010000010 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x20, 0x80, /* 001000001000 */
+ 0x0c, 0x30, /* 000011000011 */
+ 0x08, 0x20, /* 000010000010 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x20, 0x80, /* 001000001000 */
+ 0x0c, 0x30, /* 000011000011 */
+ 0x08, 0x20, /* 000010000010 */
/* 177 0xb1 '.' */
- 0x7770, /* 011101110111 */
- 0x2220, /* 001000100010 */
- 0x8880, /* 100010001000 */
- 0xddd0, /* 110111011101 */
- 0x8880, /* 100010001000 */
- 0x2220, /* 001000100010 */
- 0x7770, /* 011101110111 */
- 0x2220, /* 001000100010 */
- 0x8880, /* 100010001000 */
- 0xddd0, /* 110111011101 */
- 0x8880, /* 100010001000 */
- 0x2220, /* 001000100010 */
- 0x7770, /* 011101110111 */
- 0x2220, /* 001000100010 */
- 0x8880, /* 100010001000 */
- 0xddd0, /* 110111011101 */
- 0x8880, /* 100010001000 */
- 0x2220, /* 001000100010 */
- 0x7770, /* 011101110111 */
- 0x2220, /* 001000100010 */
- 0x8880, /* 100010001000 */
- 0xddd0, /* 110111011101 */
+ 0x77, 0x70, /* 011101110111 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x88, 0x80, /* 100010001000 */
+ 0xdd, 0xd0, /* 110111011101 */
+ 0x88, 0x80, /* 100010001000 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x77, 0x70, /* 011101110111 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x88, 0x80, /* 100010001000 */
+ 0xdd, 0xd0, /* 110111011101 */
+ 0x88, 0x80, /* 100010001000 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x77, 0x70, /* 011101110111 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x88, 0x80, /* 100010001000 */
+ 0xdd, 0xd0, /* 110111011101 */
+ 0x88, 0x80, /* 100010001000 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x77, 0x70, /* 011101110111 */
+ 0x22, 0x20, /* 001000100010 */
+ 0x88, 0x80, /* 100010001000 */
+ 0xdd, 0xd0, /* 110111011101 */
/* 178 0xb2 '.' */
- 0xf3c0, /* 111100111100 */
- 0xf7d0, /* 111101111101 */
- 0x9e70, /* 100111100111 */
- 0xdf70, /* 110111110111 */
- 0xf3c0, /* 111100111100 */
- 0xf7d0, /* 111101111101 */
- 0x9e70, /* 100111100111 */
- 0xdf70, /* 110111110111 */
- 0xf3c0, /* 111100111100 */
- 0xf7d0, /* 111101111101 */
- 0x9e70, /* 100111100111 */
- 0xdf70, /* 110111110111 */
- 0xf3c0, /* 111100111100 */
- 0xf7d0, /* 111101111101 */
- 0x9e70, /* 100111100111 */
- 0xdf70, /* 110111110111 */
- 0xf3c0, /* 111100111100 */
- 0xf7d0, /* 111101111101 */
- 0x9e70, /* 100111100111 */
- 0xdf70, /* 110111110111 */
- 0xf3c0, /* 111100111100 */
- 0xf7d0, /* 111101111101 */
+ 0xf3, 0xc0, /* 111100111100 */
+ 0xf7, 0xd0, /* 111101111101 */
+ 0x9e, 0x70, /* 100111100111 */
+ 0xdf, 0x70, /* 110111110111 */
+ 0xf3, 0xc0, /* 111100111100 */
+ 0xf7, 0xd0, /* 111101111101 */
+ 0x9e, 0x70, /* 100111100111 */
+ 0xdf, 0x70, /* 110111110111 */
+ 0xf3, 0xc0, /* 111100111100 */
+ 0xf7, 0xd0, /* 111101111101 */
+ 0x9e, 0x70, /* 100111100111 */
+ 0xdf, 0x70, /* 110111110111 */
+ 0xf3, 0xc0, /* 111100111100 */
+ 0xf7, 0xd0, /* 111101111101 */
+ 0x9e, 0x70, /* 100111100111 */
+ 0xdf, 0x70, /* 110111110111 */
+ 0xf3, 0xc0, /* 111100111100 */
+ 0xf7, 0xd0, /* 111101111101 */
+ 0x9e, 0x70, /* 100111100111 */
+ 0xdf, 0x70, /* 110111110111 */
+ 0xf3, 0xc0, /* 111100111100 */
+ 0xf7, 0xd0, /* 111101111101 */
/* 179 0xb3 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 180 0xb4 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 181 0xb5 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 182 0xb6 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfd80, /* 111111011000 */
- 0xfd80, /* 111111011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 183 0xb7 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xff80, /* 111111111000 */
- 0xff80, /* 111111111000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 184 0xb8 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 185 0xb9 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfd80, /* 111111011000 */
- 0xfd80, /* 111111011000 */
- 0x0180, /* 000000011000 */
- 0xfd80, /* 111111011000 */
- 0xfd80, /* 111111011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 186 0xba '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 187 0xbb '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xff80, /* 111111111000 */
- 0xff80, /* 111111111000 */
- 0x0180, /* 000000011000 */
- 0xfd80, /* 111111011000 */
- 0xfd80, /* 111111011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 188 0xbc '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfd80, /* 111111011000 */
- 0xfd80, /* 111111011000 */
- 0x0180, /* 000000011000 */
- 0xff80, /* 111111111000 */
- 0xff80, /* 111111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0xfd, 0x80, /* 111111011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 189 0xbd '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xff80, /* 111111111000 */
- 0xff80, /* 111111111000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0xff, 0x80, /* 111111111000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 190 0xbe '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 191 0xbf '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 192 0xc0 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 193 0xc1 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 194 0xc2 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 195 0xc3 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 196 0xc4 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 197 0xc5 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 198 0xc6 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 199 0xc7 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0df0, /* 000011011111 */
- 0x0df0, /* 000011011111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 200 0xc8 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0df0, /* 000011011111 */
- 0x0df0, /* 000011011111 */
- 0x0c00, /* 000011000000 */
- 0x0ff0, /* 000011111111 */
- 0x0ff0, /* 000011111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 201 0xc9 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0ff0, /* 000011111111 */
- 0x0ff0, /* 000011111111 */
- 0x0c00, /* 000011000000 */
- 0x0df0, /* 000011011111 */
- 0x0df0, /* 000011011111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 202 0xca '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfdf0, /* 111111011111 */
- 0xfdf0, /* 111111011111 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 203 0xcb '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0xfdf0, /* 111111011111 */
- 0xfdf0, /* 111111011111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 204 0xcc '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0df0, /* 000011011111 */
- 0x0df0, /* 000011011111 */
- 0x0c00, /* 000011000000 */
- 0x0df0, /* 000011011111 */
- 0x0df0, /* 000011011111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0xf0, /* 000011011111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 205 0xcd '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 206 0xce '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfdf0, /* 111111011111 */
- 0xfdf0, /* 111111011111 */
- 0x0000, /* 000000000000 */
- 0xfdf0, /* 111111011111 */
- 0xfdf0, /* 111111011111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0xfd, 0xf0, /* 111111011111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 207 0xcf '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 208 0xd0 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 209 0xd1 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 210 0xd2 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 211 0xd3 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0ff0, /* 000011111111 */
- 0x0ff0, /* 000011111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 212 0xd4 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 213 0xd5 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 214 0xd6 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0ff0, /* 000011111111 */
- 0x0ff0, /* 000011111111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x0f, 0xf0, /* 000011111111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 215 0xd7 '.' */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
- 0x0d80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x0d, 0x80, /* 000011011000 */
/* 216 0xd8 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0600, /* 000001100000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 217 0xd9 '.' */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0xfe00, /* 111111100000 */
- 0xfe00, /* 111111100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0xfe, 0x00, /* 111111100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 218 0xda '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x07f0, /* 000001111111 */
- 0x07f0, /* 000001111111 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x07, 0xf0, /* 000001111111 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
/* 219 0xdb '.' */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
/* 220 0xdc '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
/* 221 0xdd '.' */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
- 0xfc00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
+ 0xfc, 0x00, /* 111111000000 */
/* 222 0xde '.' */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
- 0x03f0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
+ 0x03, 0xf0, /* 000000111111 */
/* 223 0xdf '.' */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0xfff0, /* 111111111111 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 224 0xe0 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 225 0xe1 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x1980, /* 000110011000 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x3180, /* 001100011000 */
- 0x3780, /* 001101111000 */
- 0x3180, /* 001100011000 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x3180, /* 001100011000 */
- 0x7700, /* 011101110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x37, 0x80, /* 001101111000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x77, 0x00, /* 011101110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 226 0xe2 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 227 0xe3 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 228 0xe4 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 229 0xe5 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 230 0xe6 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x30c0, /* 001100001100 */
- 0x39c0, /* 001110011100 */
- 0x36e0, /* 001101101110 */
- 0x3000, /* 001100000000 */
- 0x3000, /* 001100000000 */
- 0x6000, /* 011000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x36, 0xe0, /* 001101101110 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 231 0xe7 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 232 0xe8 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 233 0xe9 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 234 0xea '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 235 0xeb '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 236 0xec '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 237 0xed '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 238 0xee '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 239 0xef '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 240 0xf0 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 241 0xf1 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 242 0xf2 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 243 0xf3 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 244 0xf4 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 245 0xf5 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 246 0xf6 '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x7fe0, /* 011111111110 */
- 0x7fe0, /* 011111111110 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 247 0xf7 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 248 0xf8 '.' */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x1980, /* 000110011000 */
- 0x0f00, /* 000011110000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 249 0xf9 '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 250 0xfa '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0600, /* 000001100000 */
- 0x0f00, /* 000011110000 */
- 0x0f00, /* 000011110000 */
- 0x0600, /* 000001100000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 251 0xfb '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 252 0xfc '.' */
/* FIXME */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 253 0xfd '.' */
- 0x0000, /* 000000000000 */
- 0x0f00, /* 000011110000 */
- 0x1f80, /* 000111111000 */
- 0x3180, /* 001100011000 */
- 0x2180, /* 001000011000 */
- 0x0300, /* 000000110000 */
- 0x0600, /* 000001100000 */
- 0x0c00, /* 000011000000 */
- 0x1840, /* 000110000100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x21, 0x80, /* 001000011000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x40, /* 000110000100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 254 0xfe '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x3fc0, /* 001111111100 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
/* 255 0xff '.' */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
- 0x0000, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
};
diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
index d50c403a6..99ebadf4b 100644
--- a/drivers/video/imsttfb.c
+++ b/drivers/video/imsttfb.c
@@ -51,11 +51,6 @@
#define eieio() /* Enforce In-order Execution of I/O */
#endif
-enum {
- IBM = 0x00,
- TVP = 0x01
-};
-
/* TwinTurbo (Cosmo) registers */
enum {
S1SA = 0, /* 0x00 */
@@ -63,7 +58,8 @@ enum {
SP = 2, /* 0x08 */
DSA = 3, /* 0x0C */
CNT = 4, /* 0x10 */
- DP_OCTRL= 5, /* 0x14 */
+ DP_OCTL = 5, /* 0x14 */
+ CLR = 6, /* 0x18 */
BI = 8, /* 0x20 */
MBC = 9, /* 0x24 */
BLTCTL = 10, /* 0x28 */
@@ -113,7 +109,7 @@ enum {
#endif
};
-/* IBM ramdac direct registers */
+/* IBM 624 RAMDAC Direct Registers */
enum {
PADDRW = 0x00,
PDATA = 0x04,
@@ -125,7 +121,7 @@ enum {
PIDXCTL = 0x1c
};
-/* IBM ramdac indirect registers */
+/* IBM 624 RAMDAC Indirect Registers */
enum {
CLKCTL = 0x02, /* (0x01) Miscellaneous Clock Control */
SYNCCTL = 0x03, /* (0x00) Sync Control */
@@ -255,7 +251,7 @@ static struct initvalues ibm_initregs[] __initdata = {
* used in the 2MB and 4MB cards, at least.
*/
{ BPP8, 0x00 },
- { BPP16, 0x00 },
+ { BPP16, 0x01 },
{ BPP24, 0x00 },
{ BPP32, 0x00 },
@@ -265,7 +261,7 @@ static struct initvalues ibm_initregs[] __initdata = {
{ SYSCLKM, 0x4f },
{ SYSCLKP, 0x00 },
{ SYSCLKC, 0x00 },
- { CURSCTL, 0x02 },
+ { CURSCTL, 0x00 },
{ CURSACCTL, 0x01 },
{ CURSACATTR, 0xa8 },
{ CURS1R, 0xff },
@@ -287,24 +283,24 @@ static struct initvalues ibm_initregs[] __initdata = {
};
static struct initvalues tvp_initregs[] __initdata = {
- { 0x6, 0x00 },
- { 0x7, 0xe4 },
- { 0xf, 0x06 },
- { 0x18, 0x80 },
- { 0x19, 0x4d },
- { 0x1a, 0x05 },
- { 0x1c, 0x00 },
- { 0x1d, 0x00 },
- { 0x1e, 0x08 },
- { 0x30, 0xff },
- { 0x31, 0xff },
- { 0x32, 0xff },
- { 0x33, 0xff },
- { 0x34, 0xff },
- { 0x35, 0xff },
- { 0x36, 0xff },
- { 0x37, 0xff },
- { 0x38, 0x00 },
+ { TVPIRICC, 0x00 },
+ { TVPIRBRC, 0xe4 },
+ { TVPIRLAC, 0x06 },
+ { TVPIRTCC, 0x80 },
+ { TVPIRMXC, 0x4d },
+ { TVPIRCLS, 0x05 },
+ { TVPIRPPG, 0x00 },
+ { TVPIRGEC, 0x00 },
+ { TVPIRMIC, 0x08 },
+ { TVPIRCKL, 0xff },
+ { TVPIRCKH, 0xff },
+ { TVPIRCRL, 0xff },
+ { TVPIRCRH, 0xff },
+ { TVPIRCGL, 0xff },
+ { TVPIRCGH, 0xff },
+ { TVPIRCBL, 0xff },
+ { TVPIRCBH, 0xff },
+ { TVPIRCKC, 0x00 },
{ TVPIRPLA, 0x00 },
{ TVPIRPPD, 0xc0 },
{ TVPIRPPD, 0xd5 },
@@ -358,13 +354,18 @@ struct fb_info_imstt {
} palette[256];
struct imstt_regvals init;
struct imstt_cursor cursor;
- volatile __u8 *frame_buffer_phys, *frame_buffer;
- volatile __u32 *dc_regs_phys, *dc_regs;
- volatile __u8 *cmap_regs_phys, *cmap_regs;
+ __u8 *frame_buffer_phys, *frame_buffer;
+ __u32 *dc_regs_phys, *dc_regs;
+ __u8 *cmap_regs_phys, *cmap_regs;
__u32 total_vram;
__u32 ramdac;
};
+enum {
+ IBM = 0,
+ TVP = 1
+};
+
#define USE_NV_MODES 1
#define INIT_BPP 8
#define INIT_XRES 640
@@ -379,6 +380,9 @@ static char noaccel __initdata = 0;
#if defined(CONFIG_PPC)
static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
#endif
+#ifdef MODULE
+static struct fb_info_imstt *fb_info_imstt_p[FB_MAX] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
static struct imstt_regvals tvp_reg_init_2 = {
512,
@@ -619,7 +623,12 @@ set_imstt_regvals_tvp (struct fb_info_imstt *p, u_int bpp)
lckl_p = init->lckl_p[1];
break;
case 24:
- /* ?!? */
+ tcc = 0x5e;
+ mxc = 0x5d;
+ lckl_n = 0xf1;
+ mlc = init->mlc[2];
+ lckl_p = init->lckl_p[2];
+ break;
case 32:
tcc = 0x46;
mxc = 0x5d;
@@ -666,7 +675,7 @@ static void
set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
{
struct imstt_regvals *init = &p->init;
- __u32 ctl, pitch, byteswap, scr, line_pitch = init->pitch * (bpp >> 3);
+ __u32 ctl, pitch, byteswap, scr;
if (p->ramdac == IBM)
set_imstt_regvals_ibm(p, bpp);
@@ -682,7 +691,6 @@ set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
* ========== ===== =====
* 8bpp 0 0
* 16bpp 0 1
- * 24bpp 1 0
* 32bpp 1 1
*/
switch (bpp) {
@@ -737,64 +745,97 @@ set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
}
switch (p->total_vram) {
- case 0x00200000:
+ case 0x200000:
scr = 0x059d | byteswap;
break;
- case 0x00400000:
- case 0x00800000:
- pitch /= 2;
+ /* case 0x400000:
+ case 0x800000: */
+ default:
+ pitch >>= 1;
scr = 0x150dd | byteswap;
break;
}
out_le32(&p->dc_regs[SCR], scr);
out_le32(&p->dc_regs[SPR], pitch);
- out_le32(&p->dc_regs[SP], (line_pitch << 16) | line_pitch);
- out_le32(&p->dc_regs[DP_OCTRL], line_pitch);
-
out_le32(&p->dc_regs[STGCTL], ctl);
}
-static void
-set_16 (struct fb_info_imstt *p, __u8 x)
+static inline void
+set_offset (struct display *disp, struct fb_info_imstt *p)
+{
+ __u32 off = disp->var.yoffset * (disp->line_length >> 3)
+ + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
+ out_le32(&p->dc_regs[SSR], off);
+}
+
+static inline void
+set_555 (struct fb_info_imstt *p)
{
if (p->ramdac == IBM) {
p->cmap_regs[PIDXHI] = 0; eieio();
p->cmap_regs[PIDXLO] = BPP16; eieio();
- p->cmap_regs[PIDXDATA] = x; eieio();
+ p->cmap_regs[PIDXDATA] = 0x01; eieio();
} else {
- /* ?!? */
+ p->cmap_regs[TVPADDRW] = TVPIRTCC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x44; eieio();
}
}
-#define set_555(_p) set_16(_p, 0x01)
-#define set_565(_p) set_16(_p, 0x03)
+static inline void
+set_565 (struct fb_info_imstt *p)
+{
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = BPP16; eieio();
+ p->cmap_regs[PIDXDATA] = 0x03; eieio();
+ } else {
+ p->cmap_regs[TVPADDRW] = TVPIRTCC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x45; eieio();
+ }
+}
static void
imstt_set_cursor (struct fb_info_imstt *p, int on)
{
struct imstt_cursor *c = &p->cursor;
- p->cmap_regs[PIDXHI] = 0;
- if (!on) {
- p->cmap_regs[PIDXLO] = CURSCTL; eieio();
- p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ if (!on) {
+ p->cmap_regs[PIDXLO] = CURSCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ } else {
+ p->cmap_regs[PIDXLO] = CURSXHI; eieio();
+ p->cmap_regs[PIDXDATA] = c->x >> 8; eieio();
+ p->cmap_regs[PIDXLO] = CURSXLO; eieio();
+ p->cmap_regs[PIDXDATA] = c->x & 0xff; eieio();
+ p->cmap_regs[PIDXLO] = CURSYHI; eieio();
+ p->cmap_regs[PIDXDATA] = c->y >> 8; eieio();
+ p->cmap_regs[PIDXLO] = CURSYLO; eieio();
+ p->cmap_regs[PIDXDATA] = c->y & 0xff; eieio();
+ p->cmap_regs[PIDXLO] = CURSCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x02; eieio();
+ }
} else {
- p->cmap_regs[PIDXLO] = CURSXHI; eieio();
- p->cmap_regs[PIDXDATA] = c->x >> 8; eieio();
- p->cmap_regs[PIDXLO] = CURSXLO; eieio();
- p->cmap_regs[PIDXDATA] = c->x & 0xff; eieio();
- p->cmap_regs[PIDXLO] = CURSYHI; eieio();
- p->cmap_regs[PIDXDATA] = c->y >> 8; eieio();
- p->cmap_regs[PIDXLO] = CURSYLO; eieio();
- p->cmap_regs[PIDXDATA] = c->y & 0xff; eieio();
- p->cmap_regs[PIDXLO] = CURSCTL; eieio();
- p->cmap_regs[PIDXDATA] = 0x02; eieio();
+ if (!on) {
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x00; eieio();
+ } else {
+ __u16 x = c->x + 0x40, y = c->y + 0x40;
+
+ p->cmap_regs[TVPCXPOH] = x >> 8; eieio();
+ p->cmap_regs[TVPCXPOL] = x & 0xff; eieio();
+ p->cmap_regs[TVPCYPOH] = y >> 8; eieio();
+ p->cmap_regs[TVPCYPOL] = y & 0xff; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x02; eieio();
+ }
}
}
static void
-imsttfb_cursor (struct display *disp, int mode, int x, int y)
+imsttfbcon_cursor (struct display *disp, int mode, int x, int y)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
struct imstt_cursor *c = &p->cursor;
@@ -827,11 +868,12 @@ imsttfb_cursor (struct display *disp, int mode, int x, int y)
}
static int
-imsttfb_set_font (struct display *disp, int width, int height)
+imsttfbcon_set_font (struct display *disp, int width, int height)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
struct imstt_cursor *c = &p->cursor;
u_int x, y;
+ __u8 fgc;
if (width > 32 || height > 32)
return -EINVAL;
@@ -839,17 +881,68 @@ imsttfb_set_font (struct display *disp, int width, int height)
c->height = height;
c->width = width;
- p->cmap_regs[PIDXHI] = 1; eieio();
- for (x = 0; x < 0x100; x++) {
- p->cmap_regs[PIDXLO] = x; eieio();
- p->cmap_regs[PIDXDATA] = 0x00; eieio();
- }
- p->cmap_regs[PIDXHI] = 1; eieio();
- for (y = 0; y < height; y++)
- for (x = 0; x < width >> 2; x++) {
- p->cmap_regs[PIDXLO] = x + y * 8; eieio();
- p->cmap_regs[PIDXDATA] = 0xff; eieio();
+ fgc = ~attr_bgcol_ec(disp, disp->conp);
+
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 1; eieio();
+ for (x = 0; x < 0x100; x++) {
+ p->cmap_regs[PIDXLO] = x; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
}
+ p->cmap_regs[PIDXHI] = 1; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 2; x++) {
+ p->cmap_regs[PIDXLO] = x + y * 8; eieio();
+ p->cmap_regs[PIDXDATA] = 0xff; eieio();
+ }
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = CURS1R; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS1G; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS1B; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS2R; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS2G; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS2B; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS3R; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS3G; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS3B; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ } else {
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] &= 0x03; eieio();
+ p->cmap_regs[TVPADDRW] = 0; eieio();
+ for (x = 0; x < 0x200; x++) {
+ p->cmap_regs[TVPCRDAT] = 0x00; eieio();
+ }
+ for (x = 0; x < 0x200; x++) {
+ p->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] &= 0x03; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 3; x++) {
+ p->cmap_regs[TVPADDRW] = x + y * 8; eieio();
+ p->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] |= 0x08; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 3; x++) {
+ p->cmap_regs[TVPADDRW] = x + y * 8; eieio();
+ p->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ p->cmap_regs[TVPCADRW] = 0x00; eieio();
+ for (x = 0; x < 12; x++) {
+ p->cmap_regs[TVPCDATA] = fgc; eieio();
+ }
+ }
return 1;
}
@@ -879,7 +972,7 @@ imstt_cursor_init (struct fb_info_imstt *p))
{
struct imstt_cursor *c = &p->cursor;
- imsttfb_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
+ imsttfbcon_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
c->enable = 1;
c->on = 1;
@@ -898,75 +991,152 @@ imstt_cursor_init (struct fb_info_imstt *p))
}
static void
-imsttfb_rectcopy (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
- __u32 Bpp = disp->var.bits_per_pixel >> 3,
- line_pitch = disp->line_length,
- fb_offset_old, fb_offset_new;
+ __u32 Bpp, line_pitch,
+ fb_offset_old, fb_offset_new,
+ sp, dp_octl, cnt, bltctl;
+
+ Bpp = disp->var.bits_per_pixel >> 3,
- fb_offset_old = sy * line_pitch + sx * Bpp;
- fb_offset_new = dy * line_pitch + dx * Bpp;
+ sy *= fontheight(disp);
+ sx *= fontwidth(disp);
+ sx *= Bpp;
+ dy *= fontheight(disp);
+ dx *= fontwidth(disp);
+ dx *= Bpp;
+ height *= fontheight(disp);
+ height--;
+ width *= fontwidth(disp);
+ width *= Bpp;
+ width--;
+
+ line_pitch = disp->line_length;
+ bltctl = 0x05;
+ sp = line_pitch << 16;
+ cnt = height << 16;
+
+ if (sy < dy) {
+ sy += height;
+ dy += height;
+ sp |= -(line_pitch) & 0xffff;
+ dp_octl = -(line_pitch) & 0xffff;
+ } else {
+ sp |= line_pitch;
+ dp_octl = line_pitch;
+ }
+ if (sx < dx) {
+ sx += width;
+ dx += width;
+ bltctl |= 0x80;
+ cnt |= -(width) & 0xffff;
+ } else {
+ cnt |= width;
+ }
+ fb_offset_old = sy * line_pitch + sx;
+ fb_offset_new = dy * line_pitch + dx;
- while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
- out_le32(&p->dc_regs[CNT], ((height - 1) << 16) | (width * Bpp - 1));
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
out_le32(&p->dc_regs[S1SA], fb_offset_old);
- /* out_le32(&p->dc_regs[S2SA], fb_offset_new); */
+ out_le32(&p->dc_regs[SP], sp);
out_le32(&p->dc_regs[DSA], fb_offset_new);
- out_le32(&p->dc_regs[BLTCTL], 0xc0000005);
- while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
- while (in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+ out_le32(&p->dc_regs[CNT], cnt);
+ out_le32(&p->dc_regs[DP_OCTL], dp_octl);
+ out_le32(&p->dc_regs[BLTCTL], bltctl);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
}
static void
-imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+imsttfbcon_clear (struct vc_data *conp, struct display *disp,
+ int sy, int sx, int height, int width)
{
- /* XXX .. */
- if (sy < dy || (sy == dy && sx < dx)) {
- switch (disp->var.bits_per_pixel) {
- case 8: fbcon_cfb8_bmove(disp, sy, sx, dy, dx, height, width); break;
- case 16: fbcon_cfb16_bmove(disp, sy, sx, dy, dx, height, width); break;
- case 24: fbcon_cfb24_bmove(disp, sy, sx, dy, dx, height, width); break;
- case 32: fbcon_cfb32_bmove(disp, sy, sx, dy, dx, height, width); break;
- }
- return;
- }
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ __u32 Bpp, line_pitch, bgc;
+
+ bgc = attr_bgcol_ec(disp, conp);
+ bgc |= (bgc << 8);
+ bgc |= (bgc << 16);
+
+ Bpp = disp->var.bits_per_pixel >> 3,
+ line_pitch = disp->line_length;
sy *= fontheight(disp);
+ sy *= line_pitch;
sx *= fontwidth(disp);
- dy *= fontheight(disp);
- dx *= fontwidth(disp);
+ sx *= Bpp;
height *= fontheight(disp);
+ height--;
width *= fontwidth(disp);
+ width *= Bpp;
+ width--;
+
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ out_le32(&p->dc_regs[DSA], sy + sx);
+ out_le32(&p->dc_regs[CNT], (height << 16) | width);
+ out_le32(&p->dc_regs[DP_OCTL], line_pitch);
+ out_le32(&p->dc_regs[BI], 0xffffffff);
+ out_le32(&p->dc_regs[MBC], 0xffffffff);
+ out_le32(&p->dc_regs[CLR], bgc);
+ out_le32(&p->dc_regs[BLTCTL], 0x200000);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+}
- imsttfb_rectcopy(disp, sy, sx, dy, dx, height, width);
+static void
+imsttfbcon_revc (struct display *disp, int sx, int sy)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ __u32 Bpp, line_pitch, height, width;
+
+ Bpp = disp->var.bits_per_pixel >> 3,
+ line_pitch = disp->line_length;
+
+ height = fontheight(disp);
+ width = fontwidth(disp) * Bpp;
+ sy *= height;
+ sy *= line_pitch;
+ sx *= width;
+ height--;
+ width--;
+
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ out_le32(&p->dc_regs[DSA], sy + sx);
+ out_le32(&p->dc_regs[S1SA], sy + sx);
+ out_le32(&p->dc_regs[CNT], (height << 16) | width);
+ out_le32(&p->dc_regs[DP_OCTL], line_pitch);
+ out_le32(&p->dc_regs[SP], line_pitch);
+ out_le32(&p->dc_regs[BLTCTL], 0x40005);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
}
#ifdef FBCON_HAS_CFB8
static struct display_switch fbcon_imstt8 = {
- fbcon_cfb8_setup, imsttfbcon_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
- fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+ fbcon_cfb8_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb8_putc,
+ fbcon_cfb8_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb8_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB16
static struct display_switch fbcon_imstt16 = {
- fbcon_cfb16_setup, imsttfbcon_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
- fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+ fbcon_cfb16_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb16_putc,
+ fbcon_cfb16_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb16_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB24
static struct display_switch fbcon_imstt24 = {
- fbcon_cfb24_setup, imsttfbcon_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
- fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+ fbcon_cfb24_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb24_putc,
+ fbcon_cfb24_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb24_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB32
static struct display_switch fbcon_imstt32 = {
- fbcon_cfb32_setup, imsttfbcon_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
- fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+ fbcon_cfb32_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb32_putc,
+ fbcon_cfb32_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb32_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
@@ -1049,11 +1219,12 @@ imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
p->palette[regno].blue = blue;
/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
- if (bpp == 16 && p->ramdac == TVP && fb_display[currcon].var.green.length == 5) {
- p->cmap_regs[PADDRW] = regno << 3; eieio();
- } else {
- p->cmap_regs[PADDRW] = regno; eieio();
- }
+ if (0 && bpp == 16) /* screws up X */
+ p->cmap_regs[PADDRW] = regno << 3;
+ else
+ p->cmap_regs[PADDRW] = regno;
+ eieio();
+
p->cmap_regs[PDATA] = red; eieio();
p->cmap_regs[PDATA] = green; eieio();
p->cmap_regs[PDATA] = blue; eieio();
@@ -1129,10 +1300,13 @@ imsttfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
}
static void
-set_disp (struct display *disp, struct fb_info_imstt *p)
+set_dispsw (struct display *disp, struct fb_info_imstt *p)
{
u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+ if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
+ disp->conp->vc_sw->con_cursor(disp->conp, CM_ERASE);
+
p->dispsw = fbcon_dummy;
disp->dispsw = &p->dispsw;
disp->dispsw_data = 0;
@@ -1150,7 +1324,7 @@ set_disp (struct display *disp, struct fb_info_imstt *p)
p->dispsw = accel ? fbcon_imstt8 : fbcon_cfb8;
#endif
break;
- case 16: /* RGB 555 */
+ case 16: /* RGB 555 or 565 */
if (disp->var.green.length != 6)
disp->var.red.offset = 10;
disp->var.red.length = 5;
@@ -1196,11 +1370,25 @@ set_disp (struct display *disp, struct fb_info_imstt *p)
break;
}
- if (p->ramdac == IBM) {
- p->dispsw.cursor = imsttfb_cursor;
- p->dispsw.set_font = imsttfb_set_font;
+ if (accel && p->ramdac != IBM) {
+ p->dispsw.cursor = 0;
+ p->dispsw.set_font = 0;
}
+#ifdef CONFIG_FB_COMPAT_XPMAC
+ set_display_info(disp);
+#endif
+}
+
+static void
+set_disp (struct display *disp, struct fb_info_imstt *p)
+{
+ u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+ disp->fb_info = &p->info;
+
+ set_dispsw(disp, p);
+
disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
disp->screen_base = (__u8 *)p->frame_buffer;
@@ -1222,8 +1410,6 @@ set_disp (struct display *disp, struct fb_info_imstt *p)
}
} else {
disp->scrollmode = SCROLL_YREDRAW;
- disp->var.yoffset = disp->var.xoffset = 0;
- out_le32(&p->dc_regs[SSR], 0);
}
disp->var.activate = 0;
@@ -1237,10 +1423,6 @@ set_disp (struct display *disp, struct fb_info_imstt *p)
disp->var.left_margin = disp->var.right_margin = 16;
disp->var.upper_margin = disp->var.lower_margin = 16;
disp->var.hsync_len = disp->var.vsync_len = 8;
-
-#ifdef CONFIG_FB_COMPAT_XPMAC
- set_display_info(disp);
-#endif
}
static int
@@ -1248,7 +1430,7 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *disp;
- u_int oldbpp, oldxres, oldyres, oldgreenlen;
+ u_int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
disp = &fb_display[con];
@@ -1273,6 +1455,7 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
oldxres = disp->var.xres;
oldyres = disp->var.yres;
oldgreenlen = disp->var.green.length;
+ oldaccel = disp->var.accel_flags;
disp->var.bits_per_pixel = var->bits_per_pixel;
disp->var.xres = var->xres;
@@ -1306,6 +1489,7 @@ imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
return err;
do_install_cmap(con, info);
}
+ *var = disp->var;
return 0;
}
@@ -1315,7 +1499,6 @@ imsttfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *inf
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *disp = &fb_display[con];
- __u32 off;
if (var->xoffset + disp->var.xres > disp->var.xres_virtual
|| var->yoffset + disp->var.yres > disp->var.yres_virtual)
@@ -1323,11 +1506,8 @@ imsttfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *inf
disp->var.xoffset = var->xoffset;
disp->var.yoffset = var->yoffset;
- if (con == currcon) {
- off = var->yoffset * (disp->line_length >> 3)
- + ((var->xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
- out_le32(&p->dc_regs[SSR], off);
- }
+ if (con == currcon)
+ set_offset(disp, p);
return 0;
}
@@ -1377,48 +1557,48 @@ imsttfb_ioctl (struct inode *inode, struct file *file, u_int cmd,
u_long arg, int con, struct fb_info *info)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
- __u8 init[2];
+ __u8 idx[2];
__u32 reg[2];
switch (cmd) {
case FBIMSTT_SETREG:
- if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
out_le32(&p->dc_regs[reg[0]], reg[1]);
return 0;
case FBIMSTT_GETREG:
- if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
reg[1] = in_le32(&p->dc_regs[reg[0]]);
if (copy_to_user((void *)(arg + 4), &reg[1], 4))
return -EFAULT;
return 0;
case FBIMSTT_SETCMAPREG:
- if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]);
return 0;
case FBIMSTT_GETCMAPREG:
- if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]);
if (copy_to_user((void *)(arg + 4), &reg[1], 4))
return -EFAULT;
return 0;
case FBIMSTT_SETIDXREG:
- if (copy_from_user(init, (void *)arg, 2))
+ if (copy_from_user(idx, (void *)arg, 2))
return -EFAULT;
p->cmap_regs[PIDXHI] = 0; eieio();
- p->cmap_regs[PIDXLO] = init[0]; eieio();
- p->cmap_regs[PIDXDATA] = init[1]; eieio();
+ p->cmap_regs[PIDXLO] = idx[0]; eieio();
+ p->cmap_regs[PIDXDATA] = idx[1]; eieio();
return 0;
case FBIMSTT_GETIDXREG:
- if (copy_from_user(init, (void *)arg, 1))
+ if (copy_from_user(idx, (void *)arg, 1))
return -EFAULT;
p->cmap_regs[PIDXHI] = 0; eieio();
- p->cmap_regs[PIDXLO] = init[0]; eieio();
- init[1] = p->cmap_regs[PIDXDATA];
- if (copy_to_user((void *)(arg + 1), &init[1], 1))
+ p->cmap_regs[PIDXLO] = idx[0]; eieio();
+ idx[1] = p->cmap_regs[PIDXDATA];
+ if (copy_to_user((void *)(arg + 1), &idx[1], 1))
return -EFAULT;
return 0;
default:
@@ -1443,21 +1623,21 @@ imsttfbcon_switch (int con, struct fb_info *info)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *old = &fb_display[currcon], *new = &fb_display[con];
- __u32 off;
if (old->cmap.len)
fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
-
- if (p->ramdac == IBM)
- imsttfb_cursor(old, CM_ERASE, p->cursor.x, p->cursor.y);
+
+ if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
+ old->conp->vc_sw->con_cursor(old->conp, CM_ERASE);
currcon = con;
if (old->var.xres != new->var.xres
|| old->var.yres != new->var.yres
|| old->var.bits_per_pixel != new->var.bits_per_pixel
- || old->var.green.length != new->var.green.length) {
- set_disp(new, p);
+ || old->var.green.length != new->var.green.length
+ || old->var.accel_flags != new->var.accel_flags) {
+ set_dispsw(new, p);
if (!compute_imstt_regvals(p, new->var.xres, new->var.yres))
return -1;
if (new->var.bits_per_pixel == 16) {
@@ -1468,53 +1648,28 @@ imsttfbcon_switch (int con, struct fb_info *info)
}
set_imstt_regvals(p, new->var.bits_per_pixel);
}
- if (old->var.yoffset != new->var.yoffset || old->var.xoffset != new->var.xoffset) {
- off = new->var.yoffset * (new->line_length >> 3)
- + ((new->var.xoffset * (new->var.bits_per_pixel >> 3)) >> 3);
- out_le32(&p->dc_regs[SSR], off);
- }
+ set_offset(new, p);
+
+ imsttfbcon_set_font(new, fontwidth(new), fontheight(new));
do_install_cmap(con, info);
return 0;
}
-static inline void
-imsttfb_rectfill (struct display *disp, u_int sy, u_int sx, u_int height, u_int width, __u32 bgx)
-{
- memset(disp->screen_base + sy + sx, bgx, height * width * (disp->var.bits_per_pixel >> 3));
-}
-
static int
imsttfbcon_updatevar (int con, struct fb_info *info)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *disp = &fb_display[con];
- struct vc_data *conp = disp->conp;
- __u32 off, yres, yoffset, sy, height;
if (con != currcon)
goto out;
- yres = disp->var.yres;
- yoffset = disp->var.yoffset;
- sy = (conp->vc_rows + disp->yscroll) * fontheight(disp);
- height = yres - conp->vc_rows * fontheight(disp);
-
- if (height && (yoffset + yres > sy)) {
- __u32 bgx = attr_bgcol_ec(disp, conp);
-
- if (sy + height > disp->var.yres_virtual)
- printk("updatevar: %u + %u > %u\n", sy, height, disp->var.yres_virtual);
- imsttfb_rectfill(disp, sy, disp->var.xoffset, height, disp->var.xres, bgx);
- }
+ if (p->ramdac == IBM)
+ imsttfbcon_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
- if (p->ramdac == IBM && (yoffset + yres <= sy))
- imsttfb_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
-
- off = disp->var.yoffset * (disp->line_length >> 3)
- + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
- out_le32(&p->dc_regs[SSR], off);
+ set_offset(disp, p);
out:
return 0;
@@ -1581,9 +1736,9 @@ init_imstt(struct fb_info_imstt *p))
tmp = in_le32(&p->dc_regs[PRC]);
if (p->ramdac == IBM)
- p->total_vram = (tmp & 0x0004) ? 0x00400000 : 0x00200000;
+ p->total_vram = (tmp & 0x0004) ? 0x400000 : 0x200000;
else
- p->total_vram = 0x00800000;
+ p->total_vram = 0x800000;
ip = (__u32 *)p->frame_buffer;
end = (__u32 *)(p->frame_buffer + p->total_vram);
@@ -1660,7 +1815,7 @@ init_imstt(struct fb_info_imstt *p))
p->disp.var.accel_flags = noaccel ? 0 : FB_ACCELF_TEXT;
set_disp(&p->disp, p);
- if (p->ramdac == IBM)
+ if (!noaccel && p->ramdac == IBM)
imstt_cursor_init(p);
if (p->disp.var.green.length == 6)
set_565(p);
@@ -1693,64 +1848,65 @@ init_imstt(struct fb_info_imstt *p))
return;
}
+ i = GET_FB_IDX(p->info.node);
tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
- printk("fb%d: %s frame buffer; %uMB vram; chip version %u\n",
- GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20, tmp);
+ printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n",
+ i, p->fix.id, p->total_vram >> 20, tmp);
+#ifdef MODULE
+ fb_info_imstt_p[i] = p;
+#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
display_info.fb_address = (__u32)p->frame_buffer_phys;
display_info.cmap_adr_address = (__u32)&p->cmap_regs_phys[PADDRW];
display_info.cmap_data_address = (__u32)&p->cmap_regs_phys[PDATA];
display_info.disp_reg_address = (__u32)p->dc_regs_phys;
- set_display_info(&p->disp);
if (!console_fb_info)
console_fb_info = &p->info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
-#if defined(CONFIG_FB_OF)
+#if defined(CONFIG_FB_OF) && !defined(MODULE)
__initfunc(void
imsttfb_of_init(struct device_node *dp))
{
struct fb_info_imstt *p;
int i;
- __u32 addr, size = 0;
+ __u32 addr = 0;
__u8 bus, devfn;
__u16 cmd;
for (i = 0; i < dp->n_addrs; i++) {
- if (dp->addrs[i].size >= 0x02000000) {
+ if (dp->addrs[i].size >= 0x02000000)
addr = dp->addrs[i].address;
- size = dp->addrs[i].size;
- }
}
- if (!size)
+ if (!addr)
return;
+ if (!pci_device_loc(dp, &bus, &devfn)) {
+ if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd) && !(cmd & PCI_COMMAND_MEMORY)) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+ }
+ }
+
p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
if (!p)
return;
-
memset(p, 0, sizeof(struct fb_info_imstt));
- p->frame_buffer_phys = (__u8 *)addr;
- p->frame_buffer = (__u8 *)ioremap(addr, size);
- p->dc_regs_phys = (__u32 *)(p->frame_buffer_phys + 0x00800000);
- p->dc_regs = (__u32 *)(p->frame_buffer + 0x00800000);
- p->cmap_regs_phys = (__u8 *)(p->frame_buffer_phys + 0x00840000);
- p->cmap_regs = (__u8 *)(p->frame_buffer + 0x00840000);
- if (dp->name[11] == '8')
+ if (dp->name[11] == '8' || (dp->name[6] == '3' && dp->name[7] == 'd'))
p->ramdac = TVP;
else
p->ramdac = IBM;
- if (!pci_device_loc(dp, &bus, &devfn)) {
- if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd)) {
- cmd |= PCI_COMMAND_MEMORY;
- pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
- }
- }
+ p->frame_buffer_phys = (__u8 *)addr;
+ p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
+ p->dc_regs_phys = (__u32 *)(addr + 0x800000);
+ p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
+ p->cmap_regs_phys = (__u8 *)(addr + 0x840000);
+ p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
init_imstt(p);
}
@@ -1759,11 +1915,60 @@ imsttfb_of_init(struct device_node *dp))
__initfunc(void
imsttfb_init(void))
{
-#if !defined(CONFIG_FB_OF)
- /* ... */
-#endif
+#if defined(CONFIG_FB_OF) && !defined(MODULE)
+ /* We don't want to be called like this. */
+ /* We rely on Open Firmware (offb) instead. */
+#elif defined(CONFIG_PCI)
+ struct pci_dev *pdev;
+ struct fb_info_imstt *p;
+ __u32 addr;
+ __u16 cmd;
+
+ for (pdev = pci_devices; pdev; pdev = pdev->next) {
+ if (!(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ && (pdev->vendor == PCI_VENDOR_ID_IMS)))
+ continue;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ if (!(cmd & PCI_COMMAND_MEMORY)) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ }
+
+ addr = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+ if (!addr)
+ continue;
+
+ p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
+ if (!p)
+ return;
+ memset(p, 0, sizeof(struct fb_info_imstt));
+
+ printk("imsttfb: device=%04x\n", pdev->device);
+
+ switch (pdev->device) {
+ case 0x9128: /* IMS,tt128mbA */
+ p->ramdac = IBM;
+ break;
+ case 0x9135: /* IMS,tt3d */
+ default:
+ p->ramdac = TVP;
+ break;
+ }
+
+ p->frame_buffer_phys = (__u8 *)addr;
+ p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
+ p->dc_regs_phys = (__u32 *)(addr + 0x800000);
+ p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
+ p->cmap_regs_phys = (__u8 *)(addr + 0x840000);
+ p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
+
+ init_imstt(p);
+ }
+#endif /* CONFIG_PCI */
}
+#ifndef MODULE
__initfunc(void
imsttfb_setup(char *options, int *ints))
{
@@ -1816,3 +2021,42 @@ imsttfb_setup(char *options, int *ints))
#endif
}
}
+
+#else /* MODULE */
+
+int
+init_module (void)
+{
+ struct fb_info_imstt *p;
+ __u32 i;
+
+ imsttfb_init();
+
+ for (i = 0; i < FB_MAX; i++) {
+ p = fb_info_imstt_p[i];
+ if (p)
+ return 0;
+ }
+
+ return -ENXIO;
+}
+
+void
+cleanup_module (void)
+{
+ struct fb_info_imstt *p;
+ __u32 i;
+
+ for (i = 0; i < FB_MAX; i++) {
+ p = fb_info_imstt_p[i];
+ if (!p)
+ continue;
+ iounmap(p->cmap_regs);
+ iounmap(p->dc_regs);
+ iounmap(p->frame_buffer);
+ kfree(p);
+ }
+}
+
+#include "macmodes.c"
+#endif /* MODULE */
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 2d0ad2924..0f964f60a 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -22,6 +22,7 @@
#include <asm/macintosh.h>
#include <linux/fb.h>
+#include <video/fbcon.h>
/* conditionalize these ?? */
#include <video/fbcon-mfb.h>
#include <video/fbcon-cfb2.h>
@@ -154,13 +155,15 @@ static void macfb_encode_fix(struct fb_fix_screeninfo *fix,
strcpy(fix->id,"Macintosh");
/*
- * X works, but screen wraps ...
+ * fbmem.c accepts non page aligned mappings now!
*/
- fix->smem_start=(char *)(mac_videobase&PAGE_MASK);
- fix->smem_offset=(mac_videobase&~PAGE_MASK);
- fix->smem_len=PAGE_ALIGN(mac_videosize);
+ fix->smem_start=(char *)mac_videobase;
+ fix->smem_len=mac_videosize;
fix->type = FB_TYPE_PACKED_PIXELS;
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
+ if (mac_depth == 1)
+ fix->visual = FB_VISUAL_MONO01;
+ else
+ fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
fix->xpanstep=0;
fix->ypanstep=0;
fix->ywrapstep=0;
@@ -203,7 +206,7 @@ static void macfb_set_disp(int con)
macfb_get_fix(&fix, con, 0);
- display->screen_base = fix.smem_start+fix.smem_offset;
+ display->screen_base = fix.smem_start;
display->visual = fix.visual;
display->type = fix.type;
display->type_aux = fix.type_aux;
@@ -212,7 +215,8 @@ static void macfb_set_disp(int con)
display->line_length = fix.line_length;
display->next_line = fix.line_length;
display->can_soft_blank = 0;
- display->inverse = inverse;
+ display->inverse =
+ (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
switch (mac_depth) {
#ifdef FBCON_HAS_MFB
@@ -251,6 +255,140 @@ static int macfb_set_var(struct fb_var_screeninfo *var, int con,
return 0;
}
+/*
+ * Color map handling - hardcoded maps!!
+ *
+ * 2.0 color map primitives, copied from atafb.c
+ */
+
+/*
+ * should be kmalloc'ed on request
+ */
+static short red256[256], green256[256], blue256[256];
+
+static short red16[]=
+ { 0x0000,0x0000,0x0000,0x0000,0x8080,0x8080,0x8080,0xc0c0,
+ 0x8080,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
+static short green16[]=
+ { 0x0000,0x0000,0x8080,0x8080,0x0000,0x0000,0x8080,0xc0c0,
+ 0x8080,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
+static short blue16[]=
+ { 0x0000,0x8080,0x0000,0x8080,0x0000,0x8080,0x0000,0xc0c0,
+ 0x8080,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
+
+static short red4[]=
+ { 0x0000,0x8080,0xffff,0xffff};
+static short green4[]=
+ { 0x0000,0x8080,0x0000,0xffff};
+static short blue4[]=
+ { 0x0000,0x8080,0x0000,0xffff};
+
+static short red2[]=
+ { 0x0000,0xffff};
+static short green2[]=
+ { 0x0000,0xffff};
+static short blue2[]=
+ { 0x0000,0xffff};
+
+struct fb_cmap default_256_colors = { 0, 256, red256, green256, blue256, NULL };
+struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL };
+struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL };
+struct fb_cmap default_2_colors = { 0, 2, red2, green2, blue2, NULL };
+
+static int mac_set_cmap256(struct fb_cmap* cmap)
+{
+ int i,start;
+ unsigned short *red,*green,*blue;
+ unsigned short cval[] = {0xffff, 0xcccc, 0x9999,
+ 0x6666, 0x3333, 0x0000 };
+ unsigned short gval[] = {0x0a0a, 0x1414, 0x1e1e,
+ 0x2828, 0x3232, 0x3c3c,
+ 0x4646, 0x5050, 0x5a5a,
+ 0x6464, 0x6e6e, 0x7878,
+ 0x8282, 0x8c8c, 0x9696,
+ 0xa0a0, 0xaaaa, 0xb4b4,
+ 0xbebe, 0xc8c8, 0xd2d2,
+ 0xdcdc, 0xe6e6, 0xf0f0};
+
+ red=cmap->red;
+ green=cmap->green;
+ blue=cmap->blue;
+ start=cmap->start;
+
+ if (start < 0)
+ return -EINVAL;
+ if (cmap->len < 255)
+ return -EINVAL;
+ /* 16 ANSI colors */
+ for (i=0 ; i < 16 ; i++) {
+ *red++ = red16[i];
+ *green++ = green16[i];
+ *blue++ = blue16[i];
+ }
+ /* 216 colors (6x6x6) map) */
+ for (i=16 ; i < 232 ; i++) {
+ *red++ = cval[(i-16)/36];
+ *green++ = cval[((i-16)/6)%6];
+ *blue++ = cval[(i-16)%6];
+ }
+ /* 24 grays */
+ for (i=232 ; i < 256 ; i++) {
+ *red = *green = *blue = gval[i-232];
+ red++;
+ green++;
+ blue++;
+ }
+ return 0;
+}
+
+static struct fb_cmap * mac_get_default_cmap(int bpp)
+{
+ if (bpp == 1)
+ return &default_2_colors;
+ if (bpp == 2)
+ return &default_4_colors;
+ if (bpp == 4)
+ return &default_16_colors;
+ return &default_256_colors;
+}
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+ switch (fsfromto) {
+ case 0:
+ memcpy(to, from, len);
+ return;
+ case 1:
+ copy_from_user(to, from, len);
+ return;
+ case 2:
+ copy_to_user(to, from, len);
+ return;
+ }
+}
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+ int size;
+ int tooff=0, fromoff=0;
+
+ if (to->start > from->start)
+ fromoff=to->start-from->start;
+ else
+ tooff=from->start-to->start;
+ size=to->len-tooff;
+ if (size > from->len-fromoff)
+ size=from->len-fromoff;
+ if (size < 0)
+ return;
+ size*=sizeof(unsigned short);
+ memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+ memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+ memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+ if (from->transp && to->transp)
+ memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
+}
+
static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
@@ -267,6 +405,8 @@ static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
#endif
+ copy_cmap(mac_get_default_cmap(fb_display[con].var.bits_per_pixel),
+ cmap, kspc ? 0 : 2);
return 0;
}
@@ -387,11 +527,9 @@ __initfunc(void macfb_init(void))
mac_videosize=mac_xbytes*mac_yres;
mac_videobase=mac_bi_data.videoaddr;
- printk("macfb_init: xres %d yres %d bpp %d addr %x size %d \n",
+ printk("macfb_init: xres %d yres %d bpp %d addr %lx size %ld \n",
mac_xres, mac_yres, mac_depth, mac_videobase, mac_videosize);
- mac_debugging_penguin(4);
-
/*
* Fill in the available video resolution
*/
@@ -421,6 +559,12 @@ __initfunc(void macfb_init(void))
macfb_set_disp(-1);
/*
+ * Fill in the 8 bit color table if required
+ */
+ if (mac_depth == 8)
+ mac_set_cmap256(&default_256_colors);
+
+ /*
* Register the nubus hook
*/
@@ -428,7 +572,6 @@ __initfunc(void macfb_init(void))
if (register_framebuffer(&fb_info) < 0)
{
- mac_boom(6);
return;
}
diff --git a/drivers/video/matroxfb.c b/drivers/video/matroxfb.c
index e9f3f44a3..5cfb98f52 100644
--- a/drivers/video/matroxfb.c
+++ b/drivers/video/matroxfb.c
@@ -2,9 +2,9 @@
*
* Hardware accelerated Matrox Millennium I, II, Mystique and G200
*
- * (c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>
*
- * Version: 1.5 1998/11/19
+ * Version: 1.9 1999/01/04
*
* MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
*
@@ -21,10 +21,14 @@
* Access device through readb|w|l and write b|w|l
* Extensive debugging stuff
*
+ * "Daniel Haun" <haund@usa.net>
+ * Testing, hardware cursor fixes
+ *
* "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
* Betatesting
*
* "Kelly French" <targon@hazmat.com>
+ * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
* Betatesting, bug reporting
*
* "Pablo Bianucci" <pbian@pccp.com.ar>
@@ -39,7 +43,14 @@
* "Paul Womar" <Paul@pwomar.demon.co.uk>
* "Owen Waller" <O.Waller@ee.qub.ac.uk>
* PPC betatesting
- *
+ *
+ * "Thomas Pornin" <pornin@bolet.ens.fr>
+ * Alpha betatesting
+ *
+ * "Pieter van Leuven" <pvl@iae.nl>
+ * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ * G100 testing
+ *
* "H. Peter Arvin" <hpa@transmeta.com>
* Ideas
*
@@ -89,6 +100,7 @@
#include <asm/io.h>
#include <asm/spinlock.h>
+#include <asm/unaligned.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -100,15 +112,17 @@
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
+#if defined(CONFIG_FB_OF)
#if defined(CONFIG_FB_COMPAT_XPMAC)
#include <asm/vc_ioctl.h>
#endif
-#if defined(CONFIG_PPC)
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#include <video/macmodes.h>
#endif
+#define FBCON_HAS_VGATEXT
+
#ifdef MATROXFB_DEBUG
#define DEBUG
@@ -156,7 +170,7 @@
/* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
/* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
/* much of PCI bandwidth is used during transfers... */
-#if defined(__i386__) || defined(__ppc__)
+#if defined(__i386__)
#define MEMCPYTOIO_MEMCPY
#else
#define MEMCPYTOIO_WRITEL
@@ -167,11 +181,17 @@
#error "Sorry, I have no idea how to do this on sparc... There is mapioaddr... With bus_type parameter..."
#endif
-#ifdef __m68k__
+#if defined(__m68k__)
#define MAP_BUSTOVIRT
#else
+#if defined(CONFIG_PPC) && defined(CONFIG_PREP) && defined(_ISA_MEM_BASE)
+/* do not tell me that PPC is not broken... if ioremap() oops with
+ invalid value written to msr... */
+#define MAP_ISAMEMBASE
+#else
#define MAP_IOREMAP
#endif
+#endif
#ifdef DEBUG
#define dprintk(X...) printk(X)
@@ -185,6 +205,9 @@
#ifndef PCI_SS_VENDOR_ID_MATROX
#define PCI_SS_VENDOR_ID_MATROX PCI_VENDOR_ID_MATROX
#endif
+#ifndef PCI_DEVICE_ID_MATROX_G200_PCI
+#define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520
+#endif
#ifndef PCI_DEVICE_ID_MATROX_G200_AGP
#define PCI_DEVICE_ID_MATROX_G200_AGP 0x0521
#endif
@@ -228,6 +251,10 @@ static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
return readb(va.vaddr + offs);
}
+static inline unsigned int mga_readw(vaddr_t va, unsigned int offs) {
+ return readw(va.vaddr + offs);
+}
+
static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
return readl(va.vaddr + offs);
}
@@ -248,6 +275,10 @@ static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
return *(volatile u_int8_t*)(va.vaddr + offs);
}
+static inline unsigned int mga_readw(vaddr_t va, unsigned int offs) {
+ return *(volatile u_int16_t*)(va.vaddr + offs);
+}
+
static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
return *(volatile u_int32_t*)(va.vaddr + offs);
}
@@ -320,9 +351,13 @@ static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags,
#ifdef MAP_BUSTOVIRT
virt->vaddr = bus_to_virt(phys);
#else
+#ifdef MAP_ISAMEMBASE
+ virt->vaddr = (void*)(phys + _ISA_MEM_BASE);
+#else
#error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
#endif
#endif
+#endif
return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
}
@@ -334,12 +369,13 @@ static inline void mga_iounmap(vaddr_t va) {
struct matroxfb_par
{
- struct fb_var_screeninfo var;
-
unsigned int final_bppShift;
- int visual; /* unfortunately, fix */
- int video_type;
unsigned int cmap_len;
+ struct {
+ unsigned int bytes;
+ unsigned int pixels;
+ unsigned int chunks;
+ } ydstorg;
void (*putc)(u_int32_t, u_int32_t, struct display*, int, int, int);
void (*putcs)(u_int32_t, u_int32_t, struct display*, const unsigned short*, int, int, int);
};
@@ -407,8 +443,8 @@ struct matrox_accel_data {
};
#ifdef CONFIG_FB_MATROX_MULTIHEAD
-#define ACCESS_FBINFO(x) (minfo->x)
-#define ACCESS_FBINFO2(info, x) (((struct matrox_fb_info*)info)->x)
+#define ACCESS_FBINFO2(info, x) (info->x)
+#define ACCESS_FBINFO(x) ACCESS_FBINFO2(minfo,x)
#define MINFO minfo
@@ -451,7 +487,7 @@ static inline struct matrox_fb_info* mxinfo(struct display* p) {
struct matrox_switch {
int (*preinit)(WPMINFO struct matrox_hw_state*);
void (*reset)(WPMINFO struct matrox_hw_state*);
- int (*init)(CPMINFO struct matrox_hw_state*, struct my_timming*);
+ int (*init)(CPMINFO struct matrox_hw_state*, struct my_timming*, struct display*);
void (*restore)(WPMINFO struct matrox_hw_state*, struct matrox_hw_state*, struct display*);
};
@@ -469,11 +505,6 @@ struct matrox_fb_info {
struct matrox_accel_data accel;
-#ifdef MATROX_2MB_WITH_4MB_ADDON
- unsigned int _mga_ydstorg;
- unsigned int _curr_ydstorg;
-#endif
-
struct pci_dev* pcidev;
struct {
@@ -511,6 +542,8 @@ struct matrox_fb_info {
int cfb4;
const int* vxres;
int cross4MB;
+ int text;
+ int plnwt;
} capable;
struct {
unsigned int size;
@@ -529,12 +562,22 @@ struct matrox_fb_info {
int novga;
int nobios;
int nopciretry;
+ int noinit;
int inverse;
int hwcursor;
int blink;
+ int sgram;
int accelerator;
+ int text_type_aux;
int video64bits;
+ unsigned int vgastep;
+ unsigned int vgastepdisp;
+ unsigned int textmode;
+ unsigned int textstep;
+ unsigned int textvram; /* character cells */
+ unsigned int ydstorg; /* offset in bytes from video start to usable memory */
+ /* 0 except for 6MB Millenium */
} devflags;
struct display_switch dispsw;
struct {
@@ -545,6 +588,7 @@ struct matrox_fb_info {
unsigned int d;
unsigned int type;
int state;
+ int redraw;
struct timer_list timer;
} cursor;
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
@@ -561,27 +605,17 @@ struct matrox_fb_info {
} cmap;
#endif
struct { unsigned red, green, blue, transp; } palette[256];
-#if defined(CONFIG_FB_COMPAT_XPMAC)
+#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
char matrox_name[32];
#endif
};
-#if defined(CONFIG_PPC)
-unsigned char nvram_read_byte(int);
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
-#endif
#if defined(CONFIG_FB_OF)
-void matrox_of_init(struct device_node *dp);
+unsigned char nvram_read_byte(int);
+int matrox_of_init(struct device_node *dp);
#endif
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-#define mga_ydstorg(x) ACCESS_FBINFO2(x, _mga_ydstorg)
-#define curr_ydstorg(x) ACCESS_FBINFO2(x, _curr_ydstorg)
-#else
-#define mga_ydstorg(x) (0)
-#define curr_ydstorg(x) (0)
-#endif
+#define curr_ydstorg(x) ACCESS_FBINFO2(x, curr.ydstorg.pixels)
#define PCI_OPTION_REG 0x40
#define PCI_MGA_INDEX 0x44
@@ -690,6 +724,9 @@ void matrox_of_init(struct device_node *dp);
#define M_DAC_VAL (M_RAMDAC_BASE+1)
#define M_PALETTE_MASK (M_RAMDAC_BASE+2)
+#define M_X_INDEX 0x00
+#define M_X_DATAREG 0x0A
+
#ifdef CONFIG_FB_MATROX_MILLENIUM
#define TVP3026_INDEX 0x00
#define TVP3026_PALWRADD 0x00
@@ -1021,19 +1058,21 @@ void matrox_of_init(struct device_node *dp);
#define isMilleniumII(x) (0)
#endif
-static void matrox_cfbX_init(struct matrox_fb_info* minfo) {
+static void matrox_cfbX_init(WPMINFO struct display* p) {
u_int32_t maccess;
u_int32_t mpitch;
u_int32_t mopmode;
DBG("matrox_cfbX_init")
-#ifdef MATROX_2MB_WITH_4MB_ADDON
- curr_ydstorg(MINFO) = mga_ydstorg(MINFO);
-#endif
- mpitch = ACCESS_FBINFO(curr.var.xres_virtual);
-
- switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+ mpitch = p->var.xres_virtual;
+
+ if (p->type == FB_TYPE_TEXT) {
+ maccess = 0x00000000;
+ mpitch = (mpitch >> 4) | 0x8000; /* set something */
+ mopmode = M_OPMODE_8BPP;
+ } else {
+ switch (p->var.bits_per_pixel) {
case 4: maccess = 0x00000000; /* accelerate as 8bpp video */
mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
mopmode = M_OPMODE_4BPP;
@@ -1041,35 +1080,28 @@ static void matrox_cfbX_init(struct matrox_fb_info* minfo) {
case 8: maccess = 0x00000000;
mopmode = M_OPMODE_8BPP;
break;
- case 16: if (ACCESS_FBINFO(curr.var.green.length) == 5)
+ case 16: if (p->var.green.length == 5)
maccess = 0xC0000001;
else
maccess = 0x40000001;
-#ifdef MATROX_2MB_WITH_4MB_ADDON
- curr_ydstorg(MINFO) >>= 1;
-#endif
mopmode = M_OPMODE_16BPP;
break;
case 24: maccess = 0x00000003;
-#ifdef MATROX_2MB_WITH_4MB_ADDON
- curr_ydstorg(MINFO) /= 3;
-#endif
mopmode = M_OPMODE_24BPP;
break;
case 32: maccess = 0x00000002;
-#ifdef MATROX_2MB_WITH_4MB_ADDON
- curr_ydstorg(MINFO) >>= 2;
-#endif
mopmode = M_OPMODE_32BPP;
break;
default: maccess = 0x00000000;
mopmode = 0x00000000;
break; /* turn off acceleration!!! */
+ }
}
mga_fifo(8);
mga_outl(M_PITCH, mpitch);
mga_outl(M_YDSTORG, curr_ydstorg(MINFO));
- mga_outl(M_PLNWT, -1);
+ if (ACCESS_FBINFO(capable.plnwt))
+ mga_outl(M_PLNWT, -1);
mga_outl(M_OPMODE, mopmode);
mga_outl(M_CXBNDRY, 0xFFFF0000);
mga_outl(M_YTOP, 0);
@@ -1685,55 +1717,34 @@ static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, i
}
}
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-static void outTi3026(CPMINFO int reg, int val) {
-
- DBG_REG("outTi3026")
-
- mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
- mga_outb(M_RAMDAC_BASE+TVP3026_X_DATAREG, val);
-}
-
-static int inTi3026(CPMINFO int reg) {
-
- DBG_REG("inTi3026")
-
- mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
- return mga_inb(M_RAMDAC_BASE+TVP3026_X_DATAREG);
+static void outDAC(CPMINFO int reg, int val) {
+ DBG_REG("outDAC");
+ mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+ mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
}
-#define POS3026_XCURCTRL 20
-
-static void matroxfb_ti3026_flashcursor(unsigned long ptr) {
-#define minfo ((struct matrox_fb_info*)ptr)
- spin_lock(&ACCESS_FBINFO(lock.DAC));
- outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA);
- ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
- add_timer(&ACCESS_FBINFO(cursor.timer));
- spin_unlock(&ACCESS_FBINFO(lock.DAC));
-#undef minfo
+static int inDAC(CPMINFO int reg) {
+ DBG_REG("inDAC");
+ mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+ return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
}
-static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
- unsigned long flags;
- u_int32_t xline;
- unsigned int i;
- unsigned int w, h;
- unsigned int cd, cu;
-
- if (ACCESS_FBINFO(currcon_display) != p)
- return;
+#define outTi3026 outDAC
+#define inTi3026 inDAC
+#define outDAC1064 outDAC
+#define inDAC1064 inDAC
- DBG("matroxfb_ti3026_createcursor");
+static void matroxfb_createcursorshape(WPMINFO struct display* p, int vmode) {
+ unsigned int h;
+ unsigned int cu, cd;
- w = fontwidth(p);
h = fontheight(p);
- if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ if (vmode & FB_VMODE_DOUBLE)
h *= 2;
cd = h;
if (cd >= 10)
- cd -= 1;
+ cd--;
switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
case CUR_NONE:
cu = cd;
@@ -1756,13 +1767,42 @@ static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
cd = h;
break;
}
- ACCESS_FBINFO(cursor.w) = w;
+ ACCESS_FBINFO(cursor.w) = fontwidth(p);
ACCESS_FBINFO(cursor.u) = cu;
ACCESS_FBINFO(cursor.d) = cd;
+}
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+#define POS3026_XCURCTRL 20
+
+static void matroxfb_ti3026_flashcursor(unsigned long ptr) {
+#define minfo ((struct matrox_fb_info*)ptr)
+ spin_lock(&ACCESS_FBINFO(lock.DAC));
+ outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA);
+ ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
+ add_timer(&ACCESS_FBINFO(cursor.timer));
+ spin_unlock(&ACCESS_FBINFO(lock.DAC));
+#undef minfo
+}
+
+static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
+ unsigned long flags;
+ u_int32_t xline;
+ unsigned int i;
+ unsigned int to;
+
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+
+ DBG("matroxfb_ti3026_createcursor");
+
+ matroxfb_createcursorshape(PMINFO p, p->var.vmode);
+
xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, 0);
- for (i = 0; i < cu; i++) {
+ to = ACCESS_FBINFO(cursor.u);
+ for (i = 0; i < to; i++) {
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
@@ -1772,7 +1812,8 @@ static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
}
- for (; i < cd; i++) {
+ to = ACCESS_FBINFO(cursor.d);
+ for (; i < to; i++) {
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 24);
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 16);
mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 8);
@@ -1818,10 +1859,11 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
x *= fontwidth(p);
y *= fontheight(p);
y -= p->var.yoffset;
- if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ if (p->var.vmode & FB_VMODE_DOUBLE)
y *= 2;
spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
- if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+ if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) {
+ ACCESS_FBINFO(cursor.redraw) = 0;
ACCESS_FBINFO(cursor.x) = x;
ACCESS_FBINFO(cursor.y) = y;
x += 64;
@@ -1851,21 +1893,6 @@ static int matroxfb_ti3026_setfont(struct display* p, int width, int height) {
#endif
#ifdef NEED_DAC1064
-static void outDAC1064(CPMINFO int reg, int val) {
-
- DBG_REG("outDAC1064");
-
- mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
- mga_outb(M_RAMDAC_BASE+M1064_X_DATAREG, val);
-}
-
-static int inDAC1064(CPMINFO int reg) {
-
- DBG_REG("inDAC1064");
-
- mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
- return mga_inb(M_RAMDAC_BASE+M1064_X_DATAREG);
-}
static void matroxfb_DAC1064_flashcursor(unsigned long ptr) {
#define minfo ((struct matrox_fb_info*)ptr)
@@ -1881,45 +1908,13 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
vaddr_t cursorbase;
u_int32_t xline;
unsigned int i;
- unsigned int w, h;
- unsigned int cu, cd;
+ unsigned int h, to;
if (ACCESS_FBINFO(currcon_display) != p)
return;
- w = fontwidth(p);
- h = fontheight(p);
+ matroxfb_createcursorshape(PMINFO p, p->var.vmode);
- if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
- h *= 2;
- cd = h;
- if (cd >= 10)
- cd -= 1;
- switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
- case CUR_NONE:
- cu = cd;
- break;
- case CUR_UNDERLINE:
- cu = cd - 2;
- break;
- case CUR_LOWER_THIRD:
- cu = (h * 2) / 3;
- break;
- case CUR_LOWER_HALF:
- cu = h / 2;
- break;
- case CUR_TWO_THIRDS:
- cu = h / 3;
- break;
- case CUR_BLOCK:
- default:
- cu = 0;
- cd = h;
- break;
- }
- ACCESS_FBINFO(cursor.w) = w;
- ACCESS_FBINFO(cursor.u) = cu;
- ACCESS_FBINFO(cursor.d) = cd;
xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
cursorbase = ACCESS_FBINFO(video.vbase);
h = ACCESS_FBINFO(features.DAC1064.cursorimage);
@@ -1927,14 +1922,16 @@ static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
WaitTillIdle();
mga_outl(M_OPMODE, M_OPMODE_32BPP);
#endif
- for (i = 0; i < cu; i++) {
+ to = ACCESS_FBINFO(cursor.u);
+ for (i = 0; i < to; i++) {
mga_writel(cursorbase, h, 0);
mga_writel(cursorbase, h+4, 0);
mga_writel(cursorbase, h+8, ~0);
mga_writel(cursorbase, h+12, ~0);
h += 16;
}
- for (; i < cd; i++) {
+ to = ACCESS_FBINFO(cursor.d);
+ for (; i < to; i++) {
mga_writel(cursorbase, h, 0);
mga_writel(cursorbase, h+4, xline);
mga_writel(cursorbase, h+8, ~0);
@@ -1972,10 +1969,11 @@ static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) {
x *= fontwidth(p);
y *= fontheight(p);
y -= p->var.yoffset;
- if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ if (p->var.vmode & FB_VMODE_DOUBLE)
y *= 2;
spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
- if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+ if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) {
+ ACCESS_FBINFO(cursor.redraw) = 0;
ACCESS_FBINFO(cursor.x) = x;
ACCESS_FBINFO(cursor.y) = y;
x += 64;
@@ -2109,6 +2107,218 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
return 1;
}
+static void matrox_text_setup(struct display* p) {
+ MINFO_FROM_DISP(p);
+
+ p->next_line = p->line_length ? p->line_length : ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
+ p->next_plane = 0;
+}
+
+static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
+ int height, int width) {
+ unsigned int srcoff;
+ unsigned int dstoff;
+ unsigned int step;
+ MINFO_FROM_DISP(p);
+
+ step = ACCESS_FBINFO(devflags.textstep);
+ srcoff = (sy * p->next_line) + (sx * step);
+ dstoff = (dy * p->next_line) + (dx * step);
+ if (dstoff < srcoff) {
+ while (height > 0) {
+ int i;
+ for (i = width; i > 0; dstoff += step, srcoff += step, i--)
+ mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
+ height--;
+ dstoff += p->next_line - width * step;
+ srcoff += p->next_line - width * step;
+ }
+ } else {
+ unsigned int off;
+
+ off = (height - 1) * p->next_line + (width - 1) * step;
+ srcoff += off;
+ dstoff += off;
+ while (height > 0) {
+ int i;
+ for (i = width; i > 0; dstoff -= step, srcoff -= step, i--)
+ mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
+ dstoff -= p->next_line - width * step;
+ srcoff -= p->next_line - width * step;
+ height--;
+ }
+ }
+}
+
+static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx,
+ int height, int width) {
+ unsigned int offs;
+ unsigned int val;
+ unsigned int step;
+ MINFO_FROM_DISP(p);
+
+ step = ACCESS_FBINFO(devflags.textstep);
+ offs = sy * p->next_line + sx * step;
+ val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8));
+ while (height > 0) {
+ int i;
+ for (i = width; i > 0; offs += step, i--)
+ mga_writew(ACCESS_FBINFO(video.vbase), offs, val);
+ offs += p->next_line - width * step;
+ height--;
+ }
+}
+
+static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
+ unsigned int offs;
+ unsigned int chr;
+ unsigned int step;
+ MINFO_FROM_DISP(p);
+
+ step = ACCESS_FBINFO(devflags.textstep);
+ offs = yy * p->next_line + xx * step;
+ chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8);
+ if (chr & 0x10000) chr |= 0x08;
+ mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr));
+}
+
+static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s,
+ int count, int yy, int xx) {
+ unsigned int offs;
+ unsigned int attr;
+ unsigned int step;
+ MINFO_FROM_DISP(p);
+
+ step = ACCESS_FBINFO(devflags.textstep);
+ offs = yy * p->next_line + xx * step;
+ attr = attr_fgcol(p,*s) | (attr_bgcol(p,*s) << 4);
+ while (count-- > 0) {
+ unsigned int chr = ((*s++) & p->charmask) << 8;
+ if (chr & 0x10000) chr ^= 0x10008;
+ mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
+ offs += step;
+ }
+}
+
+static void matrox_text_revc(struct display* p, int xx, int yy) {
+ unsigned int offs;
+ unsigned int step;
+ MINFO_FROM_DISP(p);
+
+ step = ACCESS_FBINFO(devflags.textstep);
+ offs = yy * p->next_line + xx * step + 1;
+ mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77);
+}
+
+static int matrox_text_loadfont(WPMINFO struct display* p) {
+ unsigned int fsize;
+ unsigned int width;
+ vaddr_t dst;
+ unsigned int i;
+ u_int8_t* font;
+
+ if (!p || !p->fontdata)
+ return 0;
+ width = fontwidth(p);
+ fsize = p->userfont?FNTCHARCNT(p->fontdata):256;
+
+ dst = ACCESS_FBINFO(video.vbase);
+ i = 2;
+ font = (u_int8_t*)p->fontdata;
+ mga_setr(M_SEQ_INDEX, 0x02, 0x04);
+ while (fsize--) {
+ int l;
+
+ for (l = 0; l < fontheight(p); l++) {
+ mga_writeb(dst, i, *font++);
+ if (fontwidth(p) > 8) font++;
+ i += ACCESS_FBINFO(devflags.vgastep);
+ }
+ i += (32 - fontheight(p)) * ACCESS_FBINFO(devflags.vgastep);
+ }
+ mga_setr(M_SEQ_INDEX, 0x02, 0x03);
+ return 1;
+}
+
+static void matrox_text_createcursor(WPMINFO struct display* p) {
+
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+
+ matroxfb_createcursorshape(PMINFO p, 0);
+ mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
+ mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1);
+}
+
+static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
+ unsigned int pos;
+ MINFO_FROM_DISP(p);
+
+ if (mode == CM_ERASE) {
+ if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+ mga_setr(M_CRTC_INDEX, 0x0A, 0x20);
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ }
+ return;
+ }
+ if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
+ matrox_text_createcursor(PMINFO p);
+
+ /* DO NOT CHECK cursor.x != x because of vgaHWinit moves cursor to 0,0 */
+ ACCESS_FBINFO(cursor.x) = x;
+ ACCESS_FBINFO(cursor.y) = y;
+ pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x;
+ mga_setr(M_CRTC_INDEX, 0x0F, pos);
+ mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8);
+
+ mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
+ ACCESS_FBINFO(cursor.state) = CM_DRAW;
+}
+
+static void matrox_text_round(CPMINFO struct fb_var_screeninfo* var, struct display* p) {
+ unsigned hf;
+ unsigned vf;
+ unsigned vxres;
+ unsigned ych;
+
+ hf = fontwidth(p);
+ if (!hf) hf = 8;
+ /* do not touch xres */
+ vxres = (var->xres_virtual + hf - 1) / hf;
+ if (vxres >= 256)
+ vxres = 255;
+ if (vxres < 16)
+ vxres = 16;
+ vxres = (vxres + 1) & ~1; /* must be even */
+ vf = fontheight(p);
+ if (!vf) vf = 16;
+ if (var->yres < var->yres_virtual) {
+ ych = ACCESS_FBINFO(devflags.textvram) / vxres;
+ var->yres_virtual = ych * vf;
+ } else
+ ych = var->yres_virtual / vf;
+ if (vxres * ych > ACCESS_FBINFO(devflags.textvram)) {
+ ych = ACCESS_FBINFO(devflags.textvram) / vxres;
+ var->yres_virtual = ych * vf;
+ }
+ var->xres_virtual = vxres * hf;
+}
+
+static int matrox_text_setfont(struct display* p, int width, int height) {
+ DBG("matrox_text_setfont");
+
+ if (p) {
+ MINFO_FROM_DISP(p);
+
+ matrox_text_round(PMINFO &p->var, p);
+ p->next_line = p->line_length = ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
+
+ if (p->conp)
+ matrox_text_createcursor(PMINFO p);
+ }
+ return 0;
+}
+
#define matrox_cfb16_revc matrox_cfbX_revc
#define matrox_cfb24_revc matrox_cfbX_revc
#define matrox_cfb32_revc matrox_cfbX_revc
@@ -2117,6 +2327,15 @@ static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
#define matrox_cfb24_putc matrox_cfb32_putc
#define matrox_cfb24_putcs matrox_cfb32_putcs
+#ifdef FBCON_HAS_VGATEXT
+static struct display_switch matroxfb_text = {
+ matrox_text_setup, matrox_text_bmove, matrox_text_clear,
+ matrox_text_putc, matrox_text_putcs, matrox_text_revc,
+ matrox_text_cursor, matrox_text_setfont, NULL,
+ FONTWIDTH(8)|FONTWIDTH(9)
+};
+#endif
+
#ifdef FBCON_HAS_CFB4
static struct display_switch matroxfb_cfb4 = {
fbcon_cfb4_setup, matrox_cfb4_bmove, matrox_cfb4_clear,
@@ -2178,7 +2397,10 @@ static void initMatrox(WPMINFO struct display* p) {
p->dispsw_data = NULL;
if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
- switch (p->var.bits_per_pixel) {
+ if (p->type == FB_TYPE_TEXT) {
+ swtmp = &matroxfb_text;
+ } else {
+ switch (p->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4:
swtmp = &fbcon_cfb4;
@@ -2210,12 +2432,13 @@ static void initMatrox(WPMINFO struct display* p) {
default:
p->dispsw = &fbcon_dummy;
return;
+ }
}
dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
- p->dispsw = swtmp;
- return;
- }
- switch (p->var.bits_per_pixel) {
+ } else if (p->type == FB_TYPE_TEXT) {
+ swtmp = &matroxfb_text;
+ } else {
+ switch (p->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4:
swtmp = &matroxfb_cfb4;
@@ -2247,11 +2470,11 @@ static void initMatrox(WPMINFO struct display* p) {
default:
p->dispsw = &fbcon_dummy;
return;
+ }
}
- dprintk(KERN_INFO "matroxfb: now accelerated\n");
memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
p->dispsw = &ACCESS_FBINFO(dispsw);
- if (ACCESS_FBINFO(devflags.hwcursor)) {
+ if ((p->type != FB_TYPE_TEXT) && ACCESS_FBINFO(devflags.hwcursor)) {
if (isMillenium(MINFO)) {
#ifdef CONFIG_FB_MATROX_MILLENIUM
ACCESS_FBINFO(dispsw.cursor) = matroxfb_ti3026_cursor;
@@ -2298,27 +2521,19 @@ static struct fb_var_screeninfo vesafb_defined __initdata = {
/* --------------------------------------------------------------------- */
static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
- struct matroxfb_par* p = &ACCESS_FBINFO(curr);
unsigned int pos;
unsigned short p0, p1, p2;
+ struct display *disp;
DBG("matrox_pan_var")
- p->var.xoffset = var->xoffset;
- p->var.yoffset = var->yoffset;
- if (var->vmode & FB_VMODE_YWRAP)
- p->var.vmode |= FB_VMODE_YWRAP;
- else
- p->var.vmode &= ~FB_VMODE_YWRAP;
-
- pos = (p->var.yoffset * p->var.xres_virtual + p->var.xoffset) * p->final_bppShift / 32;
- if (mga_ydstorg(MINFO)) {
- if (isInterleave(MINFO))
- pos += mga_ydstorg(MINFO) >> 3;
- else
- pos += mga_ydstorg(MINFO) >> 2;
+ disp = ACCESS_FBINFO(currcon_display);
+ if (disp->type == FB_TYPE_TEXT) {
+ pos = var->yoffset / fontheight(disp) * disp->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(disp)?fontwidth(disp):8);
+ } else {
+ pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+ pos += ACCESS_FBINFO(curr.ydstorg.chunks);
}
-
p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF;
p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8;
p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
@@ -2392,6 +2607,9 @@ static int matroxfb_get_final_bppShift(CPMINFO int bpp) {
DBG("matroxfb_get_final_bppShift")
bppshft2 = bpp;
+ if (!bppshft2) {
+ return 8;
+ }
if (isInterleave(MINFO))
bppshft2 >>= 1;
if (ACCESS_FBINFO(devflags.video64bits))
@@ -2406,6 +2624,7 @@ static int matroxfb_test_and_set_rounding(CPMINFO int xres, int bpp) {
DBG("matroxfb_test_and_set_rounding")
switch (bpp) {
+ case 0: return xres;
case 4: rounding = 128;
break;
case 8: rounding = 64;
@@ -2431,6 +2650,8 @@ static int matroxfb_pitch_adjust(CPMINFO int xres, int bpp) {
int xres_new;
DBG("matroxfb_pitch_adjust")
+
+ if (!bpp) return xres;
width = ACCESS_FBINFO(capable.vxres);
@@ -2584,10 +2805,9 @@ static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* i
return fvco;
}
-static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, int Bpp) {
+static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, struct display* p) {
unsigned int f_pll;
unsigned int pixfeed, pixin, pixpost;
- unsigned int loopfeed, loopin, looppost, loopdiv, z;
DBG("Ti3026_setpclk")
@@ -2596,52 +2816,65 @@ static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, int Bpp)
hw->DACclk[0] = pixin | 0xC0;
hw->DACclk[1] = pixfeed;
hw->DACclk[2] = pixpost | 0xB0;
- if (ACCESS_FBINFO(curr.var.bits_per_pixel) == 24) {
- loopfeed = 3; /* set lm to any possible value */
- loopin = 3 * 32 / Bpp;
+
+ if (p->type == FB_TYPE_TEXT) {
+ hw->DACreg[POS3026_XMEMPLLCTRL] = TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_PIXPLL;
+ hw->DACclk[3] = 0xFD;
+ hw->DACclk[4] = 0x3D;
+ hw->DACclk[5] = 0x70;
} else {
- loopfeed = 4;
- loopin = 4 * 32 / Bpp;
- }
- z = (110000 * loopin) / (f_pll * loopfeed);
- loopdiv = 0; /* div 2 */
- if (z < 2)
- looppost = 0;
- else if (z < 4)
- looppost = 1;
- else if (z < 8)
- looppost = 2;
- else {
- looppost = 3;
- loopdiv = z/16;
- }
- if (ACCESS_FBINFO(curr.var.bits_per_pixel) == 24) {
- hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
- hw->DACclk[4] = (65 - loopfeed) | 0x80;
- if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) {
- if (isInterleave(MINFO))
- hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
- else {
- hw->DACclk[4] &= ~0xC0;
- hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
- }
+ unsigned int loopfeed, loopin, looppost, loopdiv, z;
+ unsigned int Bpp;
+
+ Bpp = ACCESS_FBINFO(curr.final_bppShift);
+
+ if (p->var.bits_per_pixel == 24) {
+ loopfeed = 3; /* set lm to any possible value */
+ loopin = 3 * 32 / Bpp;
} else {
- if (isInterleave(MINFO))
- ; /* default... */
- else {
- hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */
- hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+ loopfeed = 4;
+ loopin = 4 * 32 / Bpp;
+ }
+ z = (110000 * loopin) / (f_pll * loopfeed);
+ loopdiv = 0; /* div 2 */
+ if (z < 2)
+ looppost = 0;
+ else if (z < 4)
+ looppost = 1;
+ else if (z < 8)
+ looppost = 2;
+ else {
+ looppost = 3;
+ loopdiv = z/16;
+ }
+ if (p->var.bits_per_pixel == 24) {
+ hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+ hw->DACclk[4] = (65 - loopfeed) | 0x80;
+ if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) {
+ if (isInterleave(MINFO))
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
+ else {
+ hw->DACclk[4] &= ~0xC0;
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
+ }
+ } else {
+ if (isInterleave(MINFO))
+ ; /* default... */
+ else {
+ hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+ }
}
+ hw->DACclk[5] = looppost | 0xF8;
+ if (ACCESS_FBINFO(devflags.mga_24bpp_fix))
+ hw->DACclk[5] ^= 0x40;
+ } else {
+ hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+ hw->DACclk[4] = 65 - loopfeed;
+ hw->DACclk[5] = looppost | 0xF0;
}
- hw->DACclk[5] = looppost | 0xF8;
- if (ACCESS_FBINFO(devflags.mga_24bpp_fix))
- hw->DACclk[5] ^= 0x40;
- } else {
- hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
- hw->DACclk[4] = 65 - loopfeed;
- hw->DACclk[5] = looppost | 0xF0;
+ hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
}
- hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
return 0;
}
#endif
@@ -2667,20 +2900,34 @@ static void var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
mt->sync = var->sync;
}
-static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
unsigned int hd, hs, he, hbe, ht;
unsigned int vd, vs, ve, vt;
unsigned int wd;
unsigned int divider;
int i;
+ int text = p->type == FB_TYPE_TEXT;
+ int fwidth;
+
+ if (text) {
+ fwidth = fontwidth(p);
+ if (!fwidth) fwidth = 8;
+ } else
+ fwidth = 8;
DBG("vgaHWinit")
hw->SEQ[0] = 0x00;
- hw->SEQ[1] = 0x01; /* or 0x09 */
+ if (fwidth == 9)
+ hw->SEQ[1] = 0x00;
+ else
+ hw->SEQ[1] = 0x01; /* or 0x09 */
hw->SEQ[2] = 0x0F; /* bitplanes */
hw->SEQ[3] = 0x00;
- hw->SEQ[4] = 0x0E;
+ if (text)
+ hw->SEQ[4] = 0x02;
+ else
+ hw->SEQ[4] = 0x0E;
/* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millenium code... Hope that by MGA1064 too */
if (m->dblscan) {
m->VTotal <<= 1;
@@ -2701,28 +2948,48 @@ static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
hw->GCTL[2] = 0x00;
hw->GCTL[3] = 0x00;
hw->GCTL[4] = 0x00;
- hw->GCTL[5] = 0x40;
- hw->GCTL[6] = 0x05;
+ if (text) {
+ hw->GCTL[5] = 0x10;
+ hw->GCTL[6] = 0x02;
+ } else {
+ hw->GCTL[5] = 0x40;
+ hw->GCTL[6] = 0x05;
+ }
hw->GCTL[7] = 0x0F;
hw->GCTL[8] = 0xFF;
/* Whole ATTR is ignored in PowerGraphics mode */
for (i = 0; i < 16; i++)
hw->ATTR[i] = i;
- hw->ATTR[16] = 0x41;
+ if (text) {
+ hw->ATTR[16] = 0x04;
+ } else {
+ hw->ATTR[16] = 0x41;
+ }
hw->ATTR[17] = 0xFF;
hw->ATTR[18] = 0x0F;
- hw->ATTR[19] = 0x00;
+ if (fwidth == 9)
+ hw->ATTR[19] = 0x08;
+ else
+ hw->ATTR[19] = 0x00;
hw->ATTR[20] = 0x00;
- hd = m->HDisplay >> 3;
- hs = m->HSyncStart >> 3;
- he = m->HSyncEnd >> 3;
- ht = m->HTotal >> 3;
- /* standard timmings are in 8pixels, but for interleaved we cannot */
- /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
- /* using 16 or more pixels per unit can save us */
- divider = ACCESS_FBINFO(curr.final_bppShift);
+ if (text) {
+ hd = m->HDisplay / fwidth;
+ hs = m->HSyncStart / fwidth;
+ he = m->HSyncEnd / fwidth;
+ ht = m->HTotal / fwidth;
+ divider = 8;
+ } else {
+ hd = m->HDisplay >> 3;
+ hs = m->HSyncStart >> 3;
+ he = m->HSyncEnd >> 3;
+ ht = m->HTotal >> 3;
+ /* standard timmings are in 8pixels, but for interleaved we cannot */
+ /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
+ /* using 16 or more pixels per unit can save us */
+ divider = ACCESS_FBINFO(curr.final_bppShift);
+ }
while (divider & 3) {
hd >>= 1;
hs >>= 1;
@@ -2747,10 +3014,16 @@ static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
vs = m->VSyncStart - 1;
ve = m->VSyncEnd - 1;
vt = m->VTotal - 2;
- if (((ht & 0x0F) == 0x0E) || ((ht & 0x0F) == 0x04))
+ /* G200 cannot work with (ht & 7) == 6 */
+ if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
ht++;
- hbe = ht;
- wd = ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.final_bppShift) / 64;
+ if (text) {
+ hbe = ht - 1;
+ wd = p->var.xres_virtual / (fwidth * 2);
+ } else {
+ hbe = ht;
+ wd = p->var.xres_virtual * ACCESS_FBINFO(curr.final_bppShift) / 64;
+ }
hw->CRTCEXT[0] = 0;
hw->CRTCEXT[5] = 0;
@@ -2770,7 +3043,10 @@ static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
((vd & 0x400) >> 8) | /* disp end */
((vd & 0xC00) >> 7) | /* vblanking start */
((vs & 0xC00) >> 5);
- hw->CRTCEXT[3] = (divider - 1) | 0x80;
+ if (text)
+ hw->CRTCEXT[3] = 0x00;
+ else
+ hw->CRTCEXT[3] = (divider - 1) | 0x80;
hw->CRTCEXT[4] = 0;
hw->CRTC[0] = ht-4;
@@ -2779,6 +3055,8 @@ static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
hw->CRTC[3] = (hbe & 0x1F) | 0x80;
hw->CRTC[4] = hs;
hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
+ if (text)
+ hw->CRTC[5] |= 0x60; /* delay sync for 3 clocks (to same picture position on MGA and VGA) */
hw->CRTC[6] = vt & 0xFF;
hw->CRTC[7] = ((vt & 0x100) >> 8) |
((vd & 0x100) >> 7) |
@@ -2790,6 +3068,8 @@ static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
((vs & 0x200) >> 2);
hw->CRTC[8] = 0x00;
hw->CRTC[9] = ((vd & 0x200) >> 4) | 0x40;
+ if (text)
+ hw->CRTC[9] |= fontheight(p) - 1;
if (m->dblscan && !m->interlaced)
hw->CRTC[9] |= 0x80;
for (i = 10; i < 16; i++)
@@ -2801,7 +3081,17 @@ static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
hw->CRTC[20] = 0x00;
hw->CRTC[21] = vd /* & 0xFF */;
hw->CRTC[22] = (vt + 1) /* & 0xFF */;
- hw->CRTC[23] = 0xC3;
+ if (text) {
+ if (ACCESS_FBINFO(devflags.textmode) == 1)
+ hw->CRTC[23] = 0xC3;
+ else
+ hw->CRTC[23] = 0xA3;
+ if (ACCESS_FBINFO(devflags.textmode) == 4)
+ hw->CRTC[20] = 0x5F;
+ else
+ hw->CRTC[20] = 0x1F;
+ } else
+ hw->CRTC[23] = 0xC3;
hw->CRTC[24] = 0xFF;
return 0;
};
@@ -2824,6 +3114,7 @@ static const unsigned char MGA1064_DAC_regs[] = {
#define POS1064_XVREFCTRL 12
#define POS1064_XMULCTRL 13
#define POS1064_XGENCTRL 15
+#define POS1064_XMISCCTRL 16
static const unsigned char MGA1064_DAC[] = {
0x00, 0x00, M1064_XCURCTRL_DIS,
@@ -2833,7 +3124,7 @@ static const unsigned char MGA1064_DAC[] = {
0x00, 0,
M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
- M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_VGA | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
+ M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_DIS | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
0x10, 0x3F, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
0x00,
0x00, 0x00, 0xFF, 0xFF};
@@ -2853,7 +3144,14 @@ __initfunc(static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int o
u_int32_t mx;
DBG("DAC1064_setmclk")
-
+
+ if (ACCESS_FBINFO(devflags.noinit)) {
+ /* read MCLK and give up... */
+ hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM);
+ hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN);
+ hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP);
+ return;
+ }
mx = hw->MXoptionReg | 0x00000004;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
mx &= ~0x000000BB;
@@ -2903,18 +3201,26 @@ __initfunc(static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int o
hw->MXoptionReg = mx;
}
-static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display *p) {
DBG("DAC1064_init_1")
memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
- switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+ if (p->type == FB_TYPE_TEXT) {
+ hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_EN
+ | M1064_XMISCCTRL_MFC_DIS
+ | M1064_XMISCCTRL_DAC_6BIT
+ | M1064_XMISCCTRL_LUT_EN;
+ hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP
+ | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+ } else {
+ switch (p->var.bits_per_pixel) {
/* case 4: not supported by MGA1064 DAC */
case 8:
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
break;
case 16:
- if (ACCESS_FBINFO(curr.var.green.length) == 5)
+ if (p->var.green.length == 5)
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
else
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
@@ -2927,6 +3233,7 @@ static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming*
break;
default:
return 1; /* unsupported depth */
+ }
}
hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl);
hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
@@ -2936,12 +3243,12 @@ static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming*
return 0;
}
-static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
DBG("DAC1064_init_2")
DAC1064_setpclk(PMINFO hw, m->pixclock);
- if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 16) { /* 256 entries */
+ if (p->var.bits_per_pixel > 16) { /* 256 entries */
int i;
for (i = 0; i < 256; i++) {
@@ -2949,8 +3256,8 @@ static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming*
hw->DACpal[i * 3 + 1] = i;
hw->DACpal[i * 3 + 2] = i;
}
- } else if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 8) {
- if (ACCESS_FBINFO(curr.var.green.length) == 5) { /* 0..31, 128..159 */
+ } else if (p->var.bits_per_pixel > 8) {
+ if (p->var.green.length == 5) { /* 0..31, 128..159 */
int i;
for (i = 0; i < 32; i++) {
@@ -2995,15 +3302,29 @@ static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const st
static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
unsigned int i;
+ unsigned int tmout;
DBG("DAC1064_restore_2")
for (i = 0; i < 3; i++)
outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
- while (!(inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40));
+ for (tmout = 500000; tmout; tmout--) {
+ if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
+ break;
+ udelay(10);
+ };
+ if (!tmout)
+ printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+
if (p && p->conp) {
- matroxfb_DAC1064_createcursor(PMINFO p);
- i = matroxfb_fastfont_tryset(PMINFO p);
+ if (p->type == FB_TYPE_TEXT) {
+ matrox_text_createcursor(PMINFO p);
+ matrox_text_loadfont(PMINFO p);
+ i = 0;
+ } else {
+ matroxfb_DAC1064_createcursor(PMINFO p);
+ i = matroxfb_fastfont_tryset(PMINFO p);
+ }
} else
i = 0;
if (i) {
@@ -3028,12 +3349,12 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st
#endif /* NEED_DAC1064 */
#ifdef CONFIG_FB_MATROX_MYSTIQUE
-static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
DBG("MGA1064_init")
- if (DAC1064_init_1(PMINFO hw, m)) return 1;
- if (vgaHWinit(PMINFO hw, m)) return 1;
+ if (DAC1064_init_1(PMINFO hw, m, p)) return 1;
+ if (vgaHWinit(PMINFO hw, m, p)) return 1;
hw->MiscOutReg = 0xCB;
if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -3043,19 +3364,19 @@ static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m
if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
hw->CRTCEXT[3] |= 0x40;
- if (DAC1064_init_2(PMINFO hw, m)) return 1;
+ if (DAC1064_init_2(PMINFO hw, m, p)) return 1;
return 0;
}
#endif
#ifdef CONFIG_FB_MATROX_G100
-static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
DBG("MGAG100_init")
- if (DAC1064_init_1(PMINFO hw, m)) return 1;
+ if (DAC1064_init_1(PMINFO hw, m, p)) return 1;
hw->MXoptionReg &= ~0x2000;
- if (vgaHWinit(PMINFO hw, m)) return 1;
+ if (vgaHWinit(PMINFO hw, m, p)) return 1;
hw->MiscOutReg = 0xEF;
if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -3065,19 +3386,27 @@ static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m
if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
hw->CRTCEXT[3] |= 0x40;
- if (DAC1064_init_2(PMINFO hw, m)) return 1;
+ if (DAC1064_init_2(PMINFO hw, m, p)) return 1;
return 0;
}
#endif /* G100 */
#ifdef CONFIG_FB_MATROX_MILLENIUM
-static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
DBG("Ti3026_init")
memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
- switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+ if (p->type == FB_TYPE_TEXT) {
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;
+ hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
+ hw->DACreg[POS3026_XMUXCTRL] = TVP3026_XMUXCTRL_VGA;
+ hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL |
+ TVP3026_XCLKCTRL_DIV4;
+ hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_6BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
+ } else {
+ switch (p->var.bits_per_pixel) {
case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
@@ -3092,7 +3421,7 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m)
break;
case 16:
/* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */
- hw->DACreg[POS3026_XTRUECOLORCTRL] = (ACCESS_FBINFO(curr.var.green.length) == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
+ hw->DACreg[POS3026_XTRUECOLORCTRL] = (p->var.green.length == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
break;
@@ -3108,8 +3437,9 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m)
break;
default:
return 1; /* TODO: failed */
+ }
}
- if (vgaHWinit(PMINFO hw, m)) return 1;
+ if (vgaHWinit(PMINFO hw, m, p)) return 1;
/* set SYNC */
hw->MiscOutReg = 0xCB;
@@ -3135,10 +3465,10 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m)
/* set interleaving */
hw->MXoptionReg &= ~0x00001000;
- if (isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
+ if ((p->type != FB_TYPE_TEXT) && isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
/* set DAC */
- Ti3026_setpclk(PMINFO hw, m->pixclock, ACCESS_FBINFO(curr.final_bppShift));
+ Ti3026_setpclk(PMINFO hw, m->pixclock, p);
return 0;
}
#endif /* CONFIG_FB_MATROX_MILLENIUM */
@@ -3148,6 +3478,10 @@ static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
DBG("matroxfb_get_cmap_len")
switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_VGATEXT
+ case 0:
+ return 16; /* pseudocolor... 16 entries HW palette */
+#endif
#ifdef FBCON_HAS_CFB4
case 4:
return 16; /* pseudocolor... 16 entries HW palette */
@@ -3175,16 +3509,17 @@ static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
return 16; /* return something reasonable... or panic()? */
}
-static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visual, int *video_cmap_len) {
+static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) {
unsigned int vramlen;
unsigned int memlen;
DBG("matroxfb_decode_var")
- if ((var->xres > var->xres_virtual) || (var->yres > var->yres_virtual) ||
- (var->xoffset > var->xres_virtual) || (var->yoffset > var->yres_virtual))
- return -EINVAL;
switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_VGATEXT
+ case 0: if (!ACCESS_FBINFO(capable.text)) return -EINVAL;
+ break;
+#endif
#ifdef FBCON_HAS_CFB4
case 4: if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL;
break;
@@ -3203,40 +3538,74 @@ static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visua
#endif
default: return -EINVAL;
}
+ *ydstorg = 0;
vramlen = ACCESS_FBINFO(video.len_usable);
- var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
- memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
- if (memlen > vramlen)
- return -EINVAL; /* out of memory */
- /* There is hardware bug that no line can cross 4MB boundary */
- /* give up for CFB24, it is impossible to easy workaround it */
- /* for other try to do something */
- if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000) && (var->bits_per_pixel != 24)) {
- int new_xres = var->xres_virtual;
-
- if (new_xres <= 512)
- new_xres = 512;
- else if (new_xres <= 1024)
- new_xres = 1024;
- else if (new_xres <= 2048)
- new_xres = 2048;
- else
- new_xres = var->xres_virtual;
- memlen = new_xres * var->bits_per_pixel / 8;
- /* if now out of memory, try shrink virtual height */
- /* but if new virtual height is smaller than visible height, return -EINVAL */
- if (var->yres_virtual * memlen > vramlen) {
- unsigned int new_yres;
-
- new_yres = vramlen / memlen;
- if (new_yres < var->yres)
- return -EINVAL;
- var->yres_virtual = new_yres;
+ if (var->bits_per_pixel) {
+ var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
+ memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+ if (memlen > vramlen) {
+ var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel);
+ memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
}
- var->xres_virtual = new_xres;
+ /* There is hardware bug that no line can cross 4MB boundary */
+ /* give up for CFB24, it is impossible to easy workaround it */
+ /* for other try to do something */
+ if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) {
+ if (var->bits_per_pixel == 24) {
+ /* sorry */
+ } else {
+ unsigned int linelen;
+ unsigned int m1 = linelen = var->xres_virtual * var->bits_per_pixel / 8;
+ unsigned int m2 = PAGE_SIZE; /* or 128 if you do not need PAGE ALIGNED address */
+ unsigned int max_yres;
+
+ while (m1) {
+ int t;
+
+ while (m2 >= m1) m2 -= m1;
+ t = m1;
+ m1 = m2;
+ m2 = t;
+ }
+ m2 = linelen * PAGE_SIZE / m2;
+ *ydstorg = m2 = 0x400000 % m2;
+ max_yres = (vramlen - m2) / linelen;
+ if (var->yres_virtual > max_yres)
+ var->yres_virtual = max_yres;
+ }
+ }
+ } else {
+ matrox_text_round(PMINFO var, p);
+#if 0
+/* we must limit pixclock by mclk...
+ Millenium I: 66 MHz = 15000
+ Millenium II: 61 MHz = 16300
+ Millenium G200: 83 MHz = 12000 */
+ if (var->pixclock < 15000)
+ var->pixclock = 15000; /* limit for "normal" gclk & mclk */
+#endif
}
- if (var->bits_per_pixel == 4) {
+ if (var->yres_virtual < var->yres)
+ var->yres = var->yres_virtual;
+ if (var->xres_virtual < var->xres)
+ var->xres = var->xres_virtual;
+ if (var->xoffset + var->xres > var->xres_virtual)
+ var->xoffset = var->xres_virtual - var->xres;
+ if (var->yoffset + var->yres > var->yres_virtual)
+ var->yoffset = var->yres_virtual - var->yres;
+
+ if (var->bits_per_pixel == 0) {
+ var->red.offset = 0;
+ var->red.length = 6;
+ var->green.offset = 0;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 6;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ *visual = MX_VISUAL_PSEUDOCOLOR;
+ } else if (var->bits_per_pixel == 4) {
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
@@ -3425,6 +3794,8 @@ __initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
ACCESS_FBINFO(features.pll.in_div_min) = 2;
ACCESS_FBINFO(features.pll.in_div_max) = 63;
ACCESS_FBINFO(features.pll.post_shift_max) = 3;
+ if (ACCESS_FBINFO(devflags.noinit))
+ return;
ti3026_setMCLK(PMINFO hw, 60000);
}
#endif
@@ -3458,7 +3829,7 @@ __initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw))
DBG("MGA1064_ramdac_init");
/* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
- ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
ACCESS_FBINFO(features.pll.ref_freq) = 14318;
ACCESS_FBINFO(features.pll.feed_div_min) = 100;
ACCESS_FBINFO(features.pll.feed_div_max) = 127;
@@ -3477,10 +3848,13 @@ __initfunc(static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw)) {
DBG("MGA1064_preinit")
/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+ ACCESS_FBINFO(capable.text) = 1;
ACCESS_FBINFO(capable.vxres) = vxres_mystique;
ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
+ if (ACCESS_FBINFO(devflags.noinit))
+ return 0; /* do not modify settings */
hw->MXoptionReg &= 0xC0000100;
hw->MXoptionReg |= 0x00094E20;
if (ACCESS_FBINFO(devflags.novga))
@@ -3513,8 +3887,9 @@ __initfunc(static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw)) {
#ifdef CONFIG_FB_MATROX_G100
/* BIOS environ */
-static int x7AF4 = 0; /* flags */
-#if 0
+static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
+ /* G100 wants 0x10, G200 SGRAM does not care... */
+#if 0
static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
#endif
@@ -3525,7 +3900,8 @@ __initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int
DBG("MGAG100_progPixClock")
- outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS);
+ outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
+ M1064_XPIXCLKCTRL_PLL_UP);
switch (flags & 3) {
case 0: reg = M1064_XPIXPLLAM; break;
case 1: reg = M1064_XPIXPLLBM; break;
@@ -3544,9 +3920,11 @@ __initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int
default: selClk |= 0x0C; break;
}
mga_outb(M_MISC_REG, selClk);
- for (clk = 65536; clk; clk--)
+ for (clk = 500000; clk; clk--) {
if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
break;
+ udelay(10);
+ };
if (!clk)
printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
@@ -3572,20 +3950,33 @@ __initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) {
static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960,
1024, 1152, 1280, 1600, 1664, 1920,
2048, 0};
+ u_int32_t reg50;
#if 0
- u_int32_t reg50;
u_int32_t q;
#endif
DBG("MGAG100_preinit")
+ /* there are some instabilities if in_div > 19 && vco < 61000 */
+ ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
+ ACCESS_FBINFO(features.pll.ref_freq) = 27000;
+ ACCESS_FBINFO(features.pll.feed_div_min) = 7;
+ ACCESS_FBINFO(features.pll.feed_div_max) = 127;
+ ACCESS_FBINFO(features.pll.in_div_min) = 1;
+ ACCESS_FBINFO(features.pll.in_div_max) = 31;
+ ACCESS_FBINFO(features.pll.post_shift_max) = 3;
+ ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT;
/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+ ACCESS_FBINFO(capable.text) = 1;
ACCESS_FBINFO(capable.vxres) = vxres_g100;
ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
-
+ ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) != FB_ACCEL_MATROX_MGAG100;
+
+ if (ACCESS_FBINFO(devflags.noinit))
+ return 0;
hw->MXoptionReg &= 0xC0000100;
- hw->MXoptionReg |= 0x00078C20;
+ hw->MXoptionReg |= 0x00078020;
if (ACCESS_FBINFO(devflags.novga))
hw->MXoptionReg &= ~0x00000100;
if (ACCESS_FBINFO(devflags.nobios))
@@ -3593,36 +3984,54 @@ __initfunc(static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw)) {
if (ACCESS_FBINFO(devflags.nopciretry))
hw->MXoptionReg |= 0x20000000;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
-
- mga_outl(M_CTLWTST, 0x03258A31); /* 03258A31 is x7AF0, default is 0x02032521 */
-#if 0
- hw->MXoptionReg |= 0x1000;
- pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
- q = def50 & 0x3000;
- reg50 = (reg50 & ~0x3000) | q;
+ reg50 &= ~0x3000;
pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
- mga_outb(0x1C05, 0x00);
- mga_outb(0x1C05, 0x80);
- udelay(100);
- mga_outb(0x1C05, 0x40);
- mga_outb(0x1C05, 0xC0);
- pci_write_config_byte(ACCESS_FBINFO(pcidev), 0x50, def50 & 0x0F);
- {
+
+ DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
+
+ if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) {
+ hw->MXoptionReg |= 0x1080;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ mga_outl(M_CTLWTST, 0x00000300);
+ /* mga_outl(M_CTLWTST, 0x03258A31); */
+ udelay(100);
+ mga_outb(0x1C05, 0x00);
+ mga_outb(0x1C05, 0x80);
+ udelay(100);
+ mga_outb(0x1C05, 0x40);
+ mga_outb(0x1C05, 0xC0);
+ udelay(100);
+ reg50 &= ~0xFF;
+ reg50 |= 0x07;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+ /* it should help with G100 */
mga_outb(M_GRAPHICS_INDEX, 6);
mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
- mga_writeb(ACCESS_FBINFO(video.vbase), 0x000, 0xAA);
- mga_writeb(ACCESS_FBINFO(video.vbase), 0x800, 0x55);
- if (mga_readb(ACCESS_FBINFO(video.vbase), 0x000) != 0xAA) {
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x0000, 0xAA);
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x0800, 0x55);
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x4000, 0x55);
+#if 0
+ if (mga_readb(ACCESS_FBINFO(video.vbase), 0x0000) != 0xAA) {
hw->MXoptionReg &= ~0x1000;
}
- }
#endif
+ } else {
+ hw->MXoptionReg |= 0x00000C00;
+ if (ACCESS_FBINFO(devflags.sgram))
+ hw->MXoptionReg |= 0x4000;
+ mga_outl(M_CTLWTST, 0x042450A1);
+ mga_outb(0x1E47, 0x00);
+ mga_outb(0x1E46, 0x00);
+ udelay(10);
+ mga_outb(0x1C05, 0x00);
+ mga_outb(0x1C05, 0x80);
+ udelay(100);
+ mga_outw(0x1E44, 0x0108);
+ }
hw->MXoptionReg = (hw->MXoptionReg & ~0x1F8000) | 0x78000;
- if (!(x7AF4 & 0x10))
- hw->MXoptionReg |= 0x4000;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
return 0;
}
@@ -3631,15 +4040,7 @@ __initfunc(static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw)) {
u_int8_t b;
DBG("MGAG100_reset")
-
- ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
- ACCESS_FBINFO(features.pll.ref_freq) = 27000;
- ACCESS_FBINFO(features.pll.feed_div_min) = 7;
- ACCESS_FBINFO(features.pll.feed_div_max) = 127;
- ACCESS_FBINFO(features.pll.in_div_min) = 1;
- ACCESS_FBINFO(features.pll.in_div_max) = 31;
- ACCESS_FBINFO(features.pll.post_shift_max) = 3;
- ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT;
+
ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
if (ACCESS_FBINFO(devflags.hwcursor))
ACCESS_FBINFO(video.len_usable) -= 1024;
@@ -3658,13 +4059,17 @@ __initfunc(static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw)) {
pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */
}
#endif
- if (x7AF4 & 8) {
- hw->MXoptionReg |= 0x40;
- pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ if (!ACCESS_FBINFO(devflags.noinit)) {
+ if (x7AF4 & 8) {
+ hw->MXoptionReg |= 0x40;
+ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+ }
+ mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
}
- mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
}
- DAC1064_setmclk(PMINFO hw, DAC1064_OPT_SCLK_PLL, 120000);
+ DAC1064_setmclk(PMINFO hw, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
+ if (ACCESS_FBINFO(devflags.noinit))
+ return;
MGAG100_setPixClock(PMINFO 4, 25175);
MGAG100_setPixClock(PMINFO 5, 28322);
if (x7AF4 & 0x10) {
@@ -3726,6 +4131,7 @@ static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *fb_info)
{
+ struct display* p;
#ifdef CONFIG_FB_MATROX_MULTIHEAD
struct matrox_fb_info* minfo = (struct matrox_fb_info*)fb_info;
#endif
@@ -3747,18 +4153,22 @@ static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green,
ACCESS_FBINFO(palette[regno].blue) = blue;
ACCESS_FBINFO(palette[regno].transp) = transp;
- if (ACCESS_FBINFO(curr.var.grayscale)) {
+ p = ACCESS_FBINFO(currcon_display);
+ if (p->var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
}
- red = CNVT_TOHW(red, ACCESS_FBINFO(curr.var.red.length));
- green = CNVT_TOHW(green, ACCESS_FBINFO(curr.var.green.length));
- blue = CNVT_TOHW(blue, ACCESS_FBINFO(curr.var.blue.length));
- transp = CNVT_TOHW(transp, ACCESS_FBINFO(curr.var.transp.length));
+ red = CNVT_TOHW(red, p->var.red.length);
+ green = CNVT_TOHW(green, p->var.green.length);
+ blue = CNVT_TOHW(blue, p->var.blue.length);
+ transp = CNVT_TOHW(transp, p->var.transp.length);
- switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
-#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4)
+ switch (p->var.bits_per_pixel) {
+#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_VGATEXT)
+#ifdef FBCON_HAS_VGATEXT
+ case 0:
+#endif
#ifdef FBCON_HAS_CFB4
case 4:
#endif
@@ -3774,45 +4184,37 @@ static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green,
#ifdef FBCON_HAS_CFB16
case 16:
ACCESS_FBINFO(cmap.cfb16[regno]) =
- (red << ACCESS_FBINFO(curr.var.red.offset)) |
- (green << ACCESS_FBINFO(curr.var.green.offset)) |
- (blue << ACCESS_FBINFO(curr.var.blue.offset)) |
- (transp << ACCESS_FBINFO(curr.var.transp.offset)); /* for 1:5:5:5 */
+ (red << p->var.red.offset) |
+ (green << p->var.green.offset) |
+ (blue << p->var.blue.offset) |
+ (transp << p->var.transp.offset); /* for 1:5:5:5 */
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:
ACCESS_FBINFO(cmap.cfb24[regno]) =
- (red << ACCESS_FBINFO(curr.var.red.offset)) |
- (green << ACCESS_FBINFO(curr.var.green.offset)) |
- (blue << ACCESS_FBINFO(curr.var.blue.offset));
+ (red << p->var.red.offset) |
+ (green << p->var.green.offset) |
+ (blue << p->var.blue.offset);
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
ACCESS_FBINFO(cmap.cfb32[regno]) =
- (red << ACCESS_FBINFO(curr.var.red.offset)) |
- (green << ACCESS_FBINFO(curr.var.green.offset)) |
- (blue << ACCESS_FBINFO(curr.var.blue.offset)) |
- (transp << ACCESS_FBINFO(curr.var.transp.offset)); /* 8:8:8:8 */
+ (red << p->var.red.offset) |
+ (green << p->var.green.offset) |
+ (blue << p->var.blue.offset) |
+ (transp << p->var.transp.offset); /* 8:8:8:8 */
break;
#endif
}
return 0;
}
-static void do_install_cmap(WPMINFO int con)
+static void do_install_cmap(WPMINFO struct display* dsp)
{
- struct display* dsp;
-
DBG("do_install_cmap")
- if (con != ACCESS_FBINFO(currcon))
- return;
- if (con >= 0)
- dsp = fb_display+con;
- else
- dsp = ACCESS_FBINFO(fbcon.disp);
if (dsp->cmap.len)
fb_set_cmap(&dsp->cmap, 1, matrox_setcolreg, &ACCESS_FBINFO(fbcon));
else
@@ -3903,7 +4305,7 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
for (i = 3; i < 6; i++)
outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
- if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[3] & 0xC0) == 0xC0)) {
+ if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
int tmout;
outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
@@ -3919,8 +4321,14 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
}
}
if (p && p->conp) {
- matroxfb_ti3026_createcursor(PMINFO p);
- i = matroxfb_fastfont_tryset(PMINFO p);
+ if (p->type == FB_TYPE_TEXT) {
+ matrox_text_createcursor(PMINFO p);
+ matrox_text_loadfont(PMINFO p);
+ i = 0;
+ } else {
+ matroxfb_ti3026_createcursor(PMINFO p);
+ i = matroxfb_fastfont_tryset(PMINFO p);
+ }
} else
i = 0;
if (i) {
@@ -3946,21 +4354,28 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_
static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
-
+ struct display* p;
DBG("matroxfb_get_fix")
#define minfo ((struct matrox_fb_info*)info)
+
+ if (con >= 0)
+ p = fb_display + con;
+ else
+ p = ACCESS_FBINFO(fbcon.disp);
+
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,"MATROX");
- fix->smem_start = (void*)ACCESS_FBINFO(video.base);
- fix->smem_len = ACCESS_FBINFO(video.len);
- fix->type = ACCESS_FBINFO(curr.video_type);
- fix->visual = ACCESS_FBINFO(curr.visual);
+ fix->smem_start = (void*)ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
+ fix->smem_len = ACCESS_FBINFO(video.len) - ACCESS_FBINFO(curr.ydstorg.bytes);
+ fix->type = p->type;
+ fix->type_aux = p->type_aux;
+ fix->visual = p->visual;
fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
fix->ypanstep = 1;
fix->ywrapstep = 0;
- fix->line_length = (ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.var.bits_per_pixel)) >> 3;
+ fix->line_length = p->line_length;
fix->mmio_start = (void*)ACCESS_FBINFO(mmio.base);
fix->mmio_len = ACCESS_FBINFO(mmio.len);
fix->accel = ACCESS_FBINFO(devflags.accelerator);
@@ -3971,14 +4386,15 @@ static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
static int matroxfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
-
+#define minfo ((struct matrox_fb_info*)info)
DBG("matroxfb_get_var")
if(con < 0)
- *var=ACCESS_FBINFO2(info, curr.var);
+ *var=ACCESS_FBINFO(fbcon.disp)->var;
else
*var=fb_display[con].var;
return 0;
+#undef minfo
}
static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
@@ -3988,12 +4404,17 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
int err;
int visual;
int cmap_len;
+ unsigned int ydstorg;
struct display* display;
int chgvar;
DBG("matroxfb_set_var")
- if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len)) != 0)
+ if (con >= 0)
+ display = fb_display + con;
+ else
+ display = ACCESS_FBINFO(fbcon.disp);
+ if ((err = matroxfb_decode_var(PMINFO display, var, &visual, &cmap_len, &ydstorg)) != 0)
return err;
switch (var->activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST: return 0;
@@ -4002,7 +4423,6 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
default: return -EINVAL; /* unknown */
}
if (con >= 0) {
- display = fb_display+con;
chgvar = ((display->var.xres != var->xres) ||
(display->var.yres != var->yres) ||
(display->var.xres_virtual != var->xres_virtual) ||
@@ -4012,18 +4432,23 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
memcmp(&display->var.green, &var->green, sizeof(var->green)) ||
memcmp(&display->var.blue, &var->blue, sizeof(var->blue)));
} else {
- display = ACCESS_FBINFO(fbcon.disp);
chgvar = 0;
}
display->var = *var;
/* cmap */
- display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase));
+ display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg;
display->visual = visual;
- display->type = FB_TYPE_PACKED_PIXELS;
- display->type_aux = 0;
display->ypanstep = 1;
display->ywrapstep = 0;
- display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ if (var->bits_per_pixel) {
+ display->type = FB_TYPE_PACKED_PIXELS;
+ display->type_aux = 0;
+ display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+ } else {
+ display->type = FB_TYPE_TEXT;
+ display->type_aux = ACCESS_FBINFO(devflags.text_type_aux);
+ display->next_line = display->line_length = (var->xres_virtual / (fontwidth(display)?fontwidth(display):8)) * ACCESS_FBINFO(devflags.textstep);
+ }
display->can_soft_blank = 1;
display->inverse = ACCESS_FBINFO(devflags.inverse);
/* conp, fb_info, vrows, cursor_x, cursor_y, fgcol, bgcol */
@@ -4036,9 +4461,21 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
if (con == ACCESS_FBINFO(currcon)) {
unsigned int pos;
- ACCESS_FBINFO(curr.var) = *var;
- ACCESS_FBINFO(curr.visual) = visual;
ACCESS_FBINFO(curr.cmap_len) = cmap_len;
+ if (display->type == FB_TYPE_TEXT) {
+ /* textmode must be in first megabyte, so no ydstorg allowed */
+ ACCESS_FBINFO(curr.ydstorg.bytes) = 0;
+ ACCESS_FBINFO(curr.ydstorg.chunks) = 0;
+ ACCESS_FBINFO(curr.ydstorg.pixels) = 0;
+ } else {
+ ydstorg += ACCESS_FBINFO(devflags.ydstorg);
+ ACCESS_FBINFO(curr.ydstorg.bytes) = ydstorg;
+ ACCESS_FBINFO(curr.ydstorg.chunks) = ydstorg >> (isInterleave(MINFO)?3:2);
+ if (var->bits_per_pixel == 4)
+ ACCESS_FBINFO(curr.ydstorg.pixels) = ydstorg;
+ else
+ ACCESS_FBINFO(curr.ydstorg.pixels) = (ydstorg * 8) / var->bits_per_pixel;
+ }
ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel);
if (visual == MX_VISUAL_PSEUDOCOLOR) {
int i;
@@ -4070,24 +4507,27 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
del_timer(&ACCESS_FBINFO(cursor.timer));
ACCESS_FBINFO(cursor.state) = CM_ERASE;
- ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt));
- pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
- if (mga_ydstorg(MINFO)) {
- if (isInterleave(MINFO))
- pos += mga_ydstorg(MINFO) >> 3;
+ ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt, display));
+ if (display->type == FB_TYPE_TEXT) {
+ if (fontheight(display))
+ pos = var->yoffset / fontheight(display) * display->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(display)?fontwidth(display):8);
else
- pos += mga_ydstorg(MINFO) >> 2;
+ pos = 0;
+ } else {
+ pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+ pos += ACCESS_FBINFO(curr.ydstorg.chunks);
}
hw->CRTC[0x0D] = pos & 0xFF;
hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display));
+ ACCESS_FBINFO(cursor.redraw) = 1;
ACCESS_FBINFO(currenthw) = hw;
ACCESS_FBINFO(newhw) = ohw;
- matrox_cfbX_init(MINFO);
- do_install_cmap(PMINFO con);
-#if defined(CONFIG_FB_COMPAT_XPMAC)
+ matrox_cfbX_init(PMINFO display);
+ do_install_cmap(PMINFO display);
+#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
int vmode, cmode;
@@ -4095,19 +4535,17 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
display_info.height = var->yres;
display_info.depth = var->bits_per_pixel;
display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8;
- if (mac_var_to_vmode(var, &vmode, &cmode)
+ if (mac_var_to_vmode(var, &vmode, &cmode))
display_info.mode = 0;
else
display_info.mode = vmode;
strcpy(display_info.name, ACCESS_FBINFO(matrox_name));
display_info.fb_address = ACCESS_FBINFO(video.base);
- /* we should not expose this addresses outside of driver. Every access to DAC must be
- exclusive locked by spinlock_irq(ACCESS_FBINFO(lock.DAC)) or by turning hardware cursor (flashing) OFF */
- display_info.cmap_adr_address = ACCESS_FBINFO(mmio.base) + M_DAC_REG;
- display_info.cmap_data_address = ACCESS_FBINFO(mmio.base) + M_DAC_VAL;
+ display_info.cmap_adr_address = 0;
+ display_info.cmap_data_address = 0;
display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
}
-#endif /* CONFIG_FB_COMPAT_XPMAC */
+#endif /* CONFIG_FB_OF && CONFIG_FB_COMPAT_XPMAC */
}
}
return 0;
@@ -4141,11 +4579,13 @@ static int matrox_getcolreg(unsigned regno, unsigned *red, unsigned *green,
static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- struct display* dsp = (con < 0) ? info->disp : fb_display+con;
+#define minfo ((struct matrox_fb_info*)info)
+ struct display* dsp = (con < 0) ? ACCESS_FBINFO(fbcon.disp)
+ : fb_display + con;
DBG("matroxfb_get_cmap")
- if (con == ACCESS_FBINFO2(info, currcon)) /* current console? */
+ if (con == ACCESS_FBINFO(currcon)) /* current console? */
return fb_get_cmap(cmap, kspc, matrox_getcolreg, info);
else if (dsp->cmap.len) /* non default colormap? */
fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
@@ -4153,6 +4593,7 @@ static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
fb_copy_cmap(fb_default_cmap(matroxfb_get_cmap_len(&dsp->var)),
cmap, kspc ? 0 : 2);
return 0;
+#undef minfo
}
static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
@@ -4160,6 +4601,7 @@ static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
{
unsigned int cmap_len;
struct display* dsp = (con < 0) ? info->disp : (fb_display + con);
+#define minfo ((struct matrox_fb_info*)info)
DBG("matroxfb_set_cmap")
@@ -4171,11 +4613,12 @@ static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
if (err)
return err;
}
- if (con == ACCESS_FBINFO2(info, currcon)) /* current console? */
+ if (con == ACCESS_FBINFO(currcon)) { /* current console? */
return fb_set_cmap(cmap, kspc, matrox_setcolreg, info);
- else
+ } else
fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
return 0;
+#undef minfo
}
static int matroxfb_ioctl(struct inode *inode, struct file *file,
@@ -4210,8 +4653,8 @@ static int matroxfb_switch(int con, struct fb_info *info)
if (ACCESS_FBINFO(currcon) >= 0) {
/* Do we have to save the colormap? */
- cmap = &fb_display[ACCESS_FBINFO2(info, currcon)].cmap;
- dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO2(info, currcon), cmap->len);
+ cmap = &(ACCESS_FBINFO(currcon_display)->cmap);
+ dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO(currcon), cmap->len);
if (cmap->len) {
dprintk(KERN_DEBUG "switch1a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp);
@@ -4224,7 +4667,7 @@ static int matroxfb_switch(int con, struct fb_info *info)
}
}
ACCESS_FBINFO(currcon) = con;
- ACCESS_FBINFO(currcon_display) = fb_display+con;
+ ACCESS_FBINFO(currcon_display) = fb_display + con;
fb_display[con].var.activate = FB_ACTIVATE_NOW;
#ifdef DEBUG
cmap = &fb_display[con].cmap;
@@ -4281,7 +4724,11 @@ static void matroxfb_blank(int blank, struct fb_info *info)
#define RS960x720 8
#define RS1152x864 9
#define RS1408x1056 10
-/* B-F */
+#define RS640x350 11
+#define RS1056x344 12 /* 132 x 43 text */
+#define RS1056x400 13 /* 132 x 50 text */
+#define RS1056x480 14 /* 132 x 60 text */
+/* 0F-FF */
static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
{ 640, 400, 48, 16, 39, 8, 96, 2, 70 },
{ 640, 480, 48, 16, 33, 10, 96, 2, 60 },
@@ -4292,27 +4739,35 @@ static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq;
{ 768, 576, 144, 16, 28, 6, 112, 4, 60 },
{ 960, 720, 144, 24, 28, 8, 112, 4, 60 },
{ 1152, 864, 192, 32, 30, 4, 128, 4, 60 },
- { 1408, 1056, 256, 40, 32, 5, 144, 5, 60 }
+ { 1408, 1056, 256, 40, 32, 5, 144, 5, 60 },
+ { 640, 350, 48, 16, 39, 8, 96, 2, 70 },
+ { 1056, 344, 96, 24, 59, 44, 160, 2, 70 },
+ { 1056, 400, 96, 24, 39, 8, 160, 2, 70 },
+ { 1056, 480, 96, 24, 36, 12, 160, 3, 60 }
};
-#define RSDepth(X) (((X) >> 4) & 0x0F)
+#define RSDepth(X) (((X) >> 8) & 0x0F)
#define RS8bpp 0x1
#define RS15bpp 0x2
#define RS16bpp 0x3
#define RS32bpp 0x4
#define RS4bpp 0x5
#define RS24bpp 0x6
-/* 7-F */
+#define RSText 0x7
+#define RSText8 0x8
+/* 9-F */
static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] __initdata = {
{ { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 8 },
{ { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
{ { 11, 5, 0}, { 6, 5, 0}, { 0, 5, 0}, { 0, 0, 0}, 16 },
{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
{ { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 4 },
- { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 }
+ { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 },
+ { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode with (default) VGA8x16 */
+ { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 } /* textmode hardwired to VGA8x8 */
};
-#define RSCreate(X,Y) ((X) | ((Y) << 4))
+#define RSCreate(X,Y) ((X) | ((Y) << 8))
static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
/* default must be first */
#ifdef FBCON_HAS_CFB8
@@ -4328,8 +4783,11 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
{ 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
#endif
#ifdef FBCON_HAS_CFB4
+ { 0x010, RSCreate(RS640x350, RS4bpp ) },
+ { 0x012, RSCreate(RS640x480, RS4bpp ) },
{ 0x102, RSCreate(RS800x600, RS4bpp ) },
{ 0x104, RSCreate(RS1024x768, RS4bpp ) },
+ { 0x106, RSCreate(RS1280x1024, RS4bpp ) },
#endif
#ifdef FBCON_HAS_CFB16
{ 0x110, RSCreate(RS640x480, RS15bpp) },
@@ -4371,6 +4829,18 @@ static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __init
{ 0x193, RSCreate(RS1152x864, RS32bpp) },
{ 0x11B, RSCreate(RS1280x1024, RS32bpp) },
{ 0x19B, RSCreate(RS1408x1056, RS32bpp) },
+ { 0x11F, RSCreate(RS1600x1200, RS32bpp) },
+#endif
+#ifdef FBCON_HAS_VGATEXT
+ { 0x002, RSCreate(RS640x400, RSText) }, /* 80x25 */
+ { 0x003, RSCreate(RS640x400, RSText) }, /* 80x25 */
+ { 0x007, RSCreate(RS640x400, RSText) }, /* 80x25 */
+ { 0x1C0, RSCreate(RS640x400, RSText8) }, /* 80x50 */
+ { 0x108, RSCreate(RS640x480, RSText8) }, /* 80x60 */
+ { 0x109, RSCreate(RS1056x400, RSText) }, /* 132x25 */
+ { 0x10A, RSCreate(RS1056x344, RSText8) }, /* 132x43 */
+ { 0x10B, RSCreate(RS1056x400, RSText8) }, /* 132x50 */
+ { 0x10C, RSCreate(RS1056x480, RSText8) }, /* 132x60 */
#endif
{ 0, 0 }};
@@ -4385,14 +4855,17 @@ static int nopan = 0; /* "matrox:nopan" */
static int no_pci_retry = 0; /* "matrox:nopciretry" */
static int novga = 0; /* "matrox:novga" */
static int nobios = 0; /* "matrox:nobios" */
+static int noinit = 1; /* "matrox:init" */
static int inverse = 0; /* "matrox:inverse" */
static int hwcursor = 1; /* "matrox:nohwcursor" */
static int blink = 1; /* "matrox:noblink" */
+static int sgram = 0; /* "matrox:sgram" */
+static int mtrr = 1; /* "matrox:nomtrr" */
static int grayscale = 0; /* "matrox:grayscale" */
static unsigned int fastfont = 0; /* "matrox:fastfont:xxxxx" */
static int dev = -1; /* "matrox:dev:xxxxx" */
static unsigned int vesa = 0x101; /* "matrox:vesa:xxxxx" */
-static unsigned int depth = 0; /* "matrox:depth:xxxxx" */
+static int depth = -1; /* "matrox:depth:xxxxx" */
static unsigned int xres = 0; /* "matrox:xres:xxxxx" */
static unsigned int yres = 0; /* "matrox:yres:xxxxx" */
static unsigned int upper = 0; /* "matrox:upper:xxxxx" */
@@ -4428,6 +4901,7 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
dev = simple_strtoul(this_opt+4, NULL, 0);
else if (!strncmp(this_opt, "depth:", 6)) {
switch (simple_strtoul(this_opt+6, NULL, 0)) {
+ case 0: depth = RSText; break;
case 4: depth = RS4bpp; break;
case 8: depth = RS8bpp; break;
case 15:depth = RS15bpp; break;
@@ -4477,6 +4951,10 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
disabled = 1;
else if (!strcmp(this_opt, "enabled")) /* noenabled does not exist */
disabled = 0;
+ else if (!strcmp(this_opt, "sgram")) /* nosgram == sdram */
+ sgram = 1;
+ else if (!strcmp(this_opt, "sdram"))
+ sgram = 0;
else {
int value = 1;
@@ -4496,6 +4974,10 @@ __initfunc(void matroxfb_setup(char *options, int *ints)) {
novga = !value;
else if (!strcmp(this_opt, "bios"))
nobios = !value;
+ else if (!strcmp(this_opt, "init"))
+ noinit = !value;
+ else if (!strcmp(this_opt, "mtrr"))
+ mtrr = value;
else if (!strcmp(this_opt, "inv24"))
inv24 = value;
else if (!strcmp(this_opt, "cross4MB"))
@@ -4533,7 +5015,7 @@ __initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned
/* at least 2MB */
if (maxSize < 0x0200000) return 0;
if (maxSize > 0x1000000) maxSize = 0x1000000;
-
+
mga_outb(M_EXTVGA_INDEX, 0x03);
mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
@@ -4600,9 +5082,12 @@ __initfunc(static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw)) {
ACCESS_FBINFO(millenium) = 1;
ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL);
ACCESS_FBINFO(capable.cfb4) = 1;
+ ACCESS_FBINFO(capable.text) = 1; /* isMilleniumII(MINFO); */
ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1;
ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor;
+ if (ACCESS_FBINFO(devflags.noinit))
+ return 0;
/* preserve VGA I/O, BIOS and PPC */
hw->MXoptionReg &= 0xC0000100;
hw->MXoptionReg |= 0x002C0000;
@@ -4688,6 +5173,7 @@ static struct video_board vbG200 __initdata = {0x1000000, FB_ACCEL_MATROX_MGAG2
#define DEVF_MILLENIUM 0x04
#define DEVF_MILLENIUM2 0x08
#define DEVF_CROSS4MB 0x10
+#define DEVF_TEXT4B 0x20
static struct board {
unsigned short vendor, device, rev, svid, sid;
unsigned int flags;
@@ -4698,8 +5184,8 @@ static struct board {
#ifdef CONFIG_FB_MATROX_MILLENIUM
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL, 0xFF,
0, 0,
- DEVF_MILLENIUM,
- 220000,
+ DEVF_MILLENIUM | DEVF_TEXT4B,
+ 230000,
&vbMillenium,
"Millennium (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, 0xFF,
@@ -4733,45 +5219,51 @@ static struct board {
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_PCI,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"MGA-G100 (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
0, 0,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"unknown G100 (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"MGA-G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_AGP,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"MGA-G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G100_AGP,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"MGA-G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"Productiva G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
0, 0,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG100,
"unknown G100 (AGP)"},
+ {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
+ 0, 0,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 250000,
+ &vbG200,
+ "unknown G200 (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
@@ -4781,7 +5273,7 @@ static struct board {
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG200,
"Mystique G200 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
@@ -4793,19 +5285,19 @@ static struct board {
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MARVEL_G200_AGP,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG200,
"Marvel G200 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G200_AGP,
DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
- 220000,
+ 230000,
&vbG200,
"MGA-G200 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
0, 0,
DEVF_VIDEO64BIT | DEVF_SWAPS,
- 220000,
+ 230000,
&vbG200,
"unknown G200 (AGP)"},
#endif
@@ -4832,7 +5324,22 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
ACCESS_FBINFO(max_pixel_clock) = b->maxclk;
printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
+ ACCESS_FBINFO(capable.plnwt) = 1;
ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT;
+ if (b->flags & DEVF_TEXT4B) {
+ ACCESS_FBINFO(devflags.vgastep) = 4;
+ ACCESS_FBINFO(devflags.textmode) = 4;
+ ACCESS_FBINFO(devflags.vgastepdisp) = 16;
+ ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16;
+ } else {
+ ACCESS_FBINFO(devflags.vgastep) = 8;
+ ACCESS_FBINFO(devflags.textmode) = 1;
+ ACCESS_FBINFO(devflags.vgastepdisp) = 64;
+ ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8;
+ }
+ ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
+ ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
+
if (ACCESS_FBINFO(capable.cross4MB) < 0)
ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
if (b->flags & DEVF_SWAPS) {
@@ -4886,8 +5393,12 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
dprintk(KERN_WARNING "matroxfb: PCI BIOS did not enable device!\n");
cmd = (cmd | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_VGA_PALETTE;
mga_option &= 0xBFFFFEFF;
+ /* we must not enable VGA, BIOS if PCI BIOS did not enable device itself */
ACCESS_FBINFO(devflags.novga) = 1;
ACCESS_FBINFO(devflags.nobios) = 1;
+ /* we must initialize device if PCI BIOS did not enable it.
+ It probably means that it is second head ... */
+ ACCESS_FBINFO(devflags.noinit) = 0;
}
mga_option |= MX_OPTION_BSWAP;
if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, NULL)) {
@@ -4931,13 +5442,16 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
ACCESS_FBINFO(video.len) = end - offs;
}
#endif
- mga_ydstorg(MINFO) = offs;
+ ACCESS_FBINFO(devflags.ydstorg) = offs;
video_base_phys += offs;
+ if (offs)
+ ACCESS_FBINFO(capable.text) = 0;
+#else
+ ACCESS_FBINFO(devflags.ydstorg) = 0;
#endif
}
- ACCESS_FBINFO(curr.video_type) = FB_TYPE_PACKED_PIXELS;
ACCESS_FBINFO(currcon) = -1;
- ACCESS_FBINFO(currcon_display) = NULL;
+ ACCESS_FBINFO(currcon_display) = d;
mga_iounmap(ACCESS_FBINFO(video.vbase));
ACCESS_FBINFO(video.base) = video_base_phys;
if (mga_ioremap(video_base_phys, ACCESS_FBINFO(video.len), MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
@@ -4950,9 +5464,11 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
if (ACCESS_FBINFO(video.len_usable) > 0x08000000)
ACCESS_FBINFO(video.len_usable) = 0x08000000;
#ifdef CONFIG_MTRR
- ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
- ACCESS_FBINFO(mtrr.vram_valid) = 1;
- printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+ if (mtrr) {
+ ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
+ ACCESS_FBINFO(mtrr.vram_valid) = 1;
+ printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+ }
#endif /* CONFIG_MTRR */
/* validate params, autodetect k, M */
@@ -4995,12 +5511,14 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
vslen = timmings[res].vslen;
if (!(fv||fh||maxclk||pixclock))
fv = timmings[res].vfreq;
- if (!depth)
+ if (depth == -1)
depth = RSDepth(RSptr->info);
}
if (sync == -1) {
sync = 0;
- if (yres < 480)
+ if (yres < 400)
+ sync |= FB_SYNC_HOR_HIGH_ACT;
+ else if (yres < 480)
sync |= FB_SYNC_VERT_HIGH_ACT;
}
if (xres < 320)
@@ -5028,6 +5546,9 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
if (tmp > pixclock) pixclock = tmp;
}
}
+ if ((depth == RSText8) && (!*ACCESS_FBINFO(fbcon.fontname))) {
+ strcpy(ACCESS_FBINFO(fbcon.fontname), "VGA8x8");
+ }
vesafb_defined.red = colors[depth-1].red;
vesafb_defined.green = colors[depth-1].green;
vesafb_defined.blue = colors[depth-1].blue;
@@ -5067,41 +5588,38 @@ __initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
+#if defined(CONFIG_FB_OF)
#if defined(CONFIG_FB_COMPAT_XPMAC)
strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */
- strcat(ACCESS_FBINFO(matrox_name), b->name);
+ strncat(ACCESS_FBINFO(matrox_name), b->name, 26);
if (!console_fb_info)
console_fb_info = &ACCESS_FBINFO(fbcon);
#endif
-#if defined(CONFIG_PPC)
if ((xres <= 640) && (yres <= 480)) {
struct fb_var_screeninfo var;
+ int default_vmode = nvram_read_byte(NV_VMODE);
+ int default_cmode = nvram_read_byte(NV_CMODE);
- if (default_vmode == VMODE_NVRAM)
- default_vmode = nvram_read_byte(NV_VMODE);
if ((default_vmode <= 0) || (default_vmode > VMODE_MAX))
default_vmode = VMODE_640_480_60;
- if (default_cmode == CMODE_NVRAM)
- default_cmode = nvram_read_byte(NV_CMODE);
if ((default_cmode < CMODE_8) || (default_cmode > CMODE_32))
default_cmode = CMODE_8;
if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
var.accel_flags = vesafb_defined.accel_flags;
- vesafb_defined = var;
+ var.xoffset = var.yoffset = 0;
+ vesafb_defined = var; /* Note: mac_vmode_to_var() doesnot set all parameters */
}
}
#endif
{
int pixel_size = vesafb_defined.bits_per_pixel;
- int avamem = ACCESS_FBINFO(video.len_usable);
- vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO xres, pixel_size);
+ vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO vesafb_defined.xres, pixel_size);
if (nopan) {
vesafb_defined.yres_virtual = vesafb_defined.yres;
} else {
- vesafb_defined.yres_virtual = (avamem * 8 / (pixel_size * vesafb_defined.xres_virtual)) & ~0x1F;
- if (vesafb_defined.yres_virtual < vesafb_defined.yres)
- vesafb_defined.yres_virtual = vesafb_defined.yres;
+ vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
+ to yres_virtual * xres_virtual < 2^32 */
}
}
if (matroxfb_set_var(&vesafb_defined, -2, &ACCESS_FBINFO(fbcon))) {
@@ -5180,11 +5698,13 @@ __initfunc(static int matrox_init(void)) {
ACCESS_FBINFO(devflags.inverse) = inverse;
ACCESS_FBINFO(devflags.novga) = novga;
ACCESS_FBINFO(devflags.nobios) = nobios;
+ ACCESS_FBINFO(devflags.noinit) = noinit;
ACCESS_FBINFO(devflags.nopciretry) = no_pci_retry;
ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24;
ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
ACCESS_FBINFO(devflags.hwcursor) = hwcursor;
ACCESS_FBINFO(devflags.blink) = blink;
+ ACCESS_FBINFO(devflags.sgram) = sgram;
ACCESS_FBINFO(capable.cross4MB) = cross4MB;
ACCESS_FBINFO(fastfont.size) = fastfont;
@@ -5234,9 +5754,11 @@ __initfunc(void matroxfb_init(void))
}
#if defined(CONFIG_FB_OF)
-__initfunc(void matrox_of_init(struct device_node *dp)) {
+__initfunc(int matrox_of_init(struct device_node *dp)) {
DBG("matrox_of_init");
matrox_init();
+ if (!fb_list) return -ENXIO;
+ return 0;
}
#endif /* CONFIG_FB_OF */
@@ -5258,6 +5780,12 @@ MODULE_PARM(novga, "i");
MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
MODULE_PARM(nobios, "i");
MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
+MODULE_PARM(noinit, "i");
+MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
+MODULE_PARM(mtrr, "i");
+MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
+MODULE_PARM(sgram, "i");
+MODULE_PARM_DESC(sgram, "Indicates that G200 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
MODULE_PARM(inv24, "i");
MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
MODULE_PARM(inverse, "i");
@@ -5270,7 +5798,7 @@ MODULE_PARM(dev, "i");
MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)");
#endif
MODULE_PARM(vesa, "i");
-MODULE_PARM_DESC(vesa, "Startup videomode (0x100-0x1FF) (default=0x101)");
+MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
MODULE_PARM(xres, "i");
MODULE_PARM_DESC(xres, "Horizontal resolutioni (px), overrides xres from vesa (default=vesa)");
MODULE_PARM(yres, "i");
@@ -5292,7 +5820,7 @@ MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (defau
MODULE_PARM(sync, "i");
MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
MODULE_PARM(depth, "i");
-MODULE_PARM_DESC(depth, "Color depth (8,15,16,24,32) (default=vesa)");
+MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
MODULE_PARM(maxclk, "i");
MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
MODULE_PARM(fh, "i");
@@ -5309,7 +5837,7 @@ MODULE_PARM_DESC(fastfont, "Specifies, how much memory should be used for font d
MODULE_PARM(grayscale, "i");
MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
MODULE_PARM(cross4MB, "i");
-MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. It cannot at least on Millennium (I/II).");
+MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
__initfunc(int init_module(void)) {
@@ -5321,7 +5849,7 @@ __initfunc(int init_module(void)) {
#endif /* DEBUG */
if (depth == 0)
- depth = 0; /* default */
+ depth = RSText;
else if (depth == 4)
depth = RS4bpp;
else if (depth == 8)
@@ -5334,9 +5862,9 @@ __initfunc(int init_module(void)) {
depth = RS24bpp;
else if (depth == 32)
depth = RS32bpp;
- else {
+ else if (depth != -1) {
printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
- depth = 0;
+ depth = -1;
}
matrox_init();
if (!fb_list) return -ENXIO;
diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c
index ea5afadd8..177493d68 100644
--- a/drivers/video/mdacon.c
+++ b/drivers/video/mdacon.c
@@ -331,7 +331,7 @@ __initfunc(static const char *mdacon_startup(void))
mda_type_name = "MDA";
if (! mda_detect()) {
- printk("mdacon: MDA card not detected.");
+ printk("mdacon: MDA card not detected.\n");
return NULL;
}
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index d66176242..f74486863 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -68,7 +68,6 @@ struct fb_info_offb {
static int ofonly = 0;
-
/*
* Interface used by the world
*/
@@ -251,8 +250,10 @@ static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
- fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- cmap, kspc ? 0 : 2);
+ {
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+ }
return 0;
}
@@ -270,8 +271,8 @@ static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return -ENOSYS;
if (!fb_display[con].cmap.len) { /* no colormap allocated? */
- if ((err = fb_alloc_cmap(&fb_display[con].cmap,
- 1<<fb_display[con].var.bits_per_pixel, 0)))
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
return err;
}
if (con == currcon) /* current console? */
@@ -302,7 +303,7 @@ extern void imsttfb_of_init(struct device_node *dp);
extern void chips_of_init(struct device_node *dp);
#endif /* CONFIG_FB_CT65550 */
#ifdef CONFIG_FB_MATROX
-extern void matrox_of_init(struct device_node *dp);
+extern int matrox_of_init(struct device_node *dp);
#endif /* CONFIG_FB_MATROX */
#ifdef CONFIG_FB_CONTROL
extern void control_of_init(struct device_node *dp);
@@ -329,43 +330,43 @@ __initfunc(void offb_init(void))
/* If we're booted from BootX... */
if (prom_num_displays == 0 && boot_infos != 0) {
unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;
- if (!ofonly) {
- /* find the device node corresponding to the macos display */
- for (dp = displays; dp != NULL; dp = dp->next) {
- int i;
- /*
- * Grrr... It looks like the MacOS ATI driver
- * munges the assigned-addresses property (but
- * the AAPL,address value is OK).
- */
- if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
- unsigned int *ap = (unsigned int *)
- get_property(dp, "AAPL,address", NULL);
- if (ap != NULL) {
- dp->addrs[0].address = *ap;
- dp->addrs[0].size = 0x01000000;
- }
+ /* find the device node corresponding to the macos display */
+ for (dp = displays; dp != NULL; dp = dp->next) {
+ int i;
+ /*
+ * Grrr... It looks like the MacOS ATI driver
+ * munges the assigned-addresses property (but
+ * the AAPL,address value is OK).
+ */
+ if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
+ unsigned int *ap = (unsigned int *)
+ get_property(dp, "AAPL,address", NULL);
+ if (ap != NULL) {
+ dp->addrs[0].address = *ap;
+ dp->addrs[0].size = 0x01000000;
}
- /*
- * See if the display address is in one of the address
- * ranges for this display.
- */
- for (i = 0; i < dp->n_addrs; ++i) {
- if (dp->addrs[i].address <= addr
- && addr < dp->addrs[i].address + dp->addrs[i].size)
- break;
- }
- if (i < dp->n_addrs) {
- printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
- macos_display = dp;
+ }
+ /*
+ * See if the display address is in one of the address
+ * ranges for this display.
+ */
+ for (i = 0; i < dp->n_addrs; ++i) {
+ if (dp->addrs[i].address <= addr
+ && addr < dp->addrs[i].address + dp->addrs[i].size)
break;
- }
+ }
+ if (i < dp->n_addrs) {
+ printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
+ macos_display = dp;
+ break;
}
}
/* initialize it */
- if (macos_display == NULL || !offb_init_driver(macos_display)) {
- offb_init_fb("MacOS display", "MacOS display",
+ if (ofonly || macos_display == NULL
+ || !offb_init_driver(macos_display)) {
+ offb_init_fb(macos_display? macos_display->name: "MacOS display",
+ macos_display? macos_display->full_name: "MacOS display",
boot_infos->dispDeviceRect[2],
boot_infos->dispDeviceRect[3],
boot_infos->dispDeviceDepth,
@@ -399,11 +400,13 @@ __initfunc(static int offb_init_driver(struct device_node *dp))
}
#endif /* CONFIG_FB_ATY */
#ifdef CONFIG_FB_S3TRIO
- if (s3triofb_init_of(dp))
+ if (!strncmp(dp->name, "S3Trio", 6)) {
+ s3triofb_init_of(dp);
return 1;
+ }
#endif /* CONFIG_FB_S3TRIO */
#ifdef CONFIG_FB_IMSTT
- if (!strncmp(dp->name, "IMS,tt128mb", 11)) {
+ if (!strncmp(dp->name, "IMS,tt", 6)) {
imsttfb_of_init(dp);
return 1;
}
@@ -522,17 +525,20 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name,
fix->type = FB_TYPE_PACKED_PIXELS;
fix->type_aux = 0;
- /* XXX kludge for ati */
- if (strncmp(name, "ATY,", 4) == 0) {
- info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
- info->cmap_data = info->cmap_adr + 1;
- }
-
if (depth == 8)
- fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
+ {
+ /* XXX kludge for ati */
+ if (strncmp(name, "ATY,", 4) == 0) {
+ unsigned long base = address & 0xff000000UL;
+ info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
+ info->cmap_data = info->cmap_adr + 1;
+ }
+ fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_STATIC_PSEUDOCOLOR;
+ }
else
- fix->visual = FB_VISUAL_TRUECOLOR;
+ fix->visual = /*info->cmap_adr ? FB_VISUAL_DIRECTCOLOR
+ : */FB_VISUAL_TRUECOLOR;
var->xoffset = var->yoffset = 0;
var->bits_per_pixel = depth;
@@ -610,10 +616,14 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name,
disp->dispsw = &fbcon_cfb16;
disp->dispsw_data = info->fbcon_cmap.cfb16;
for (i = 0; i < 16; i++)
- info->fbcon_cmap.cfb16[i] =
- (((default_blu[i] >> 3) & 0x1f) << 10) |
- (((default_grn[i] >> 3) & 0x1f) << 5) |
- ((default_red[i] >> 3) & 0x1f);
+ if (fix->visual == FB_VISUAL_TRUECOLOR)
+ info->fbcon_cmap.cfb16[i] =
+ (((default_blu[i] >> 3) & 0x1f) << 10) |
+ (((default_grn[i] >> 3) & 0x1f) << 5) |
+ ((default_red[i] >> 3) & 0x1f);
+ else
+ info->fbcon_cmap.cfb16[i] =
+ (i << 10) | (i << 5) | i;
break;
#endif
#ifdef FBCON_HAS_CFB32
@@ -621,9 +631,14 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name,
disp->dispsw = &fbcon_cfb32;
disp->dispsw_data = info->fbcon_cmap.cfb32;
for (i = 0; i < 16; i++)
- info->fbcon_cmap.cfb32[i] = (default_blu[i] << 16) |
- (default_grn[i] << 8) |
- default_red[i];
+ if (fix->visual == FB_VISUAL_TRUECOLOR)
+ info->fbcon_cmap.cfb32[i] =
+ (default_blu[i] << 16) |
+ (default_grn[i] << 8) |
+ default_red[i];
+ else
+ info->fbcon_cmap.cfb32[i] =
+ (i << 16) | (i << 8) | i;
break;
#endif
default:
@@ -674,9 +689,10 @@ __initfunc(static void offb_init_fb(const char *name, const char *full_name,
display_info.disp_reg_address = 0;
/* XXX kludge for ati */
if (strncmp(name, "ATY,", 4) == 0) {
- display_info.disp_reg_address = address + 0x7ffc00;
- display_info.cmap_adr_address = address + 0x7ffcc0;
- display_info.cmap_data_address = address + 0x7ffcc1;
+ unsigned long base = address & 0xff000000UL;
+ display_info.disp_reg_address = base + 0x7ffc00;
+ display_info.cmap_adr_address = base + 0x7ffcc0;
+ display_info.cmap_data_address = base + 0x7ffcc1;
}
console_fb_info = &info->info;
}
@@ -789,7 +805,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
info2->palette[regno].green = green;
info2->palette[regno].blue = blue;
- *info2->cmap_adr = regno;
+ *info2->cmap_adr = regno;/* On some chipsets, add << 3 in 15 bits */
mach_eieio();
*info2->cmap_data = red;
mach_eieio();
@@ -802,8 +818,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
switch (info2->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
- info2->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
- regno;
+ info2->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
break;
#endif
#ifdef FBCON_HAS_CFB32
@@ -825,8 +840,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (fb_display[con].cmap.len)
fb_set_cmap(&fb_display[con].cmap, 1, offb_setcolreg, info);
else
- fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
- 1, offb_setcolreg, info);
+ {
+ int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+ fb_set_cmap(fb_default_cmap(size), 1, offb_setcolreg, info);
+ }
}
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
new file mode 100644
index 000000000..c26958e7b
--- /dev/null
+++ b/drivers/video/pm2fb.c
@@ -0,0 +1,1494 @@
+/*
+ * Permedia2 framebuffer driver.
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven.
+ * --------------------------------------------------------------------------
+ * $Id: pm2fb.c,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "pm2fb.h"
+#ifdef CONFIG_FB_PM2_CVPPC
+#include "cvisionppc.h"
+#endif
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error "The endianness of the target host has not been defined."
+#endif
+
+#undef PM2FB_MASTER_DEBUG
+#ifdef PM2FB_MASTER_DEBUG
+#define DPRINTK(a,b...) printk("pm2fb: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif
+
+#define PICOS2KHZ(a) (1000000000UL/(a))
+#define KHZ2PICOS(a) (1000000000UL/(a))
+
+#ifdef CONFIG_APUS
+#define MMAP(a,b) (unsigned char* )kernel_map((unsigned long )(a), \
+ b, KERNELMAP_NOCACHE_SER, NULL)
+#else
+#define MMAP(a,b) ioremap(a, b)
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef __powerpc__
+#define eieio()
+#endif
+
+struct pm2fb_par {
+ unsigned long pixclock; /* pixclock in KHz */
+ unsigned long width; /* width of virtual screen */
+ unsigned long height; /* height of virtual screen */
+ unsigned long hsstart; /* horiz. sync start */
+ unsigned long hsend; /* horiz. sync end */
+ unsigned long hbend; /* horiz. blank end (also gate end) */
+ unsigned long htotal; /* total width (w/ sync & blank) */
+ unsigned long vsstart; /* vert. sync start */
+ unsigned long vsend; /* vert. sync end */
+ unsigned long vbend; /* vert. blank end */
+ unsigned long vtotal; /* total height (w/ sync & blank) */
+ unsigned long stride; /* screen stride */
+ unsigned long base; /* screen base (xoffset+yoffset) */
+ unsigned long depth; /* screen depth (8, 16, 24 or 32) */
+ unsigned long video; /* video control (hsync,vsync) */
+};
+
+#define OPTF_OLD_MEM 0x00000001
+#define OPTF_YPAN 0x00000002
+static struct {
+ char font[40];
+ unsigned long flags;
+ struct pm2fb_par user_mode;
+} pm2fb_options;
+
+static const struct {
+ char name[16];
+ struct pm2fb_par par;
+} user_mode[] __initdata = {
+ {"640x480-60",
+ {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}},
+ {"640x480-72",
+ {31199,640,480,6,16,48,207,8,10,39,518,80,0,8,121}},
+ {"640x480-75",
+ {31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}},
+ {"640x480-90",
+ {39909,640,480,8,18,48,207,24,38,53,532,80,0,8,121}},
+ {"640x480-100",
+ {44899,640,480,8,40,52,211,21,33,51,530,80,0,8,121}},
+ {"800x600-56",
+ {35999,800,600,6,24,56,255,0,2,25,624,100,0,8,41}},
+ {"800x600-60",
+ {40000,800,600,10,42,64,263,0,4,28,627,100,0,8,41}},
+ {"800x600-70",
+ {44899,800,600,6,42,52,251,8,20,36,635,100,0,8,105}},
+ {"800x600-72",
+ {50000,800,600,14,44,60,259,36,42,66,665,100,0,8,41}},
+ {"800x600-75",
+ {49497,800,600,4,24,64,263,0,3,25,624,100,0,8,41}},
+ {"800x600-90",
+ {56637,800,600,2,18,48,247,7,18,35,634,100,0,8,41}},
+ {"800x600-100",
+ {67499,800,600,0,16,70,269,6,10,25,624,100,0,8,41}},
+ {"1024x768-60",
+ {64998,1024,768,6,40,80,335,2,8,38,805,128,0,8,121}},
+ {"1024x768-70",
+ {74996,1024,768,6,40,76,331,2,8,38,805,128,0,8,121}},
+ {"1024x768-72",
+ {74996,1024,768,6,40,66,321,2,8,38,805,128,0,8,121}},
+ {"1024x768-75",
+ {78932,1024,768,4,28,72,327,0,3,32,799,128,0,8,41}},
+ {"1024x768-90",
+ {100000,1024,768,0,24,72,327,20,35,77,844,128,0,8,121}},
+ {"1024x768-100",
+ {109998,1024,768,0,22,92,347,0,7,24,791,128,0,8,121}},
+ {"1024x768-illo",
+ {120322,1024,768,12,48,120,375,3,7,32,799,128,0,8,41}},
+ {"1152x864-60",
+ {80000,1152,864,16,44,76,363,5,10,52,915,144,0,8,41}},
+ {"1152x864-70",
+ {100000,1152,864,10,48,90,377,12,23,81,944,144,0,8,41}},
+ {"1152x864-75",
+ {109998,1152,864,6,42,78,365,44,52,138,1001,144,0,8,41}},
+ {"1152x864-80",
+ {109998,1152,864,4,32,72,359,29,36,94,957,144,0,8,41}},
+ {"1280x1024-60",
+ {107991,1280,1024,12,40,102,421,0,3,42,1065,160,0,8,41}},
+ {"1280x1024-70",
+ {125992,1280,1024,20,48,102,421,0,5,42,1065,160,0,8,41}},
+ {"1280x1024-74",
+ {134989,1280,1024,8,44,108,427,0,29,40,1063,160,0,8,41}},
+ {"1280x1024-75",
+ {134989,1280,1024,4,40,102,421,0,3,42,1065,160,0,8,41}},
+ {"1600x1200-60",
+ {155981,1600,1200,8,48,112,511,9,17,70,1269,200,0,8,121}},
+ {"1600x1200-66",
+ {171998,1600,1200,10,44,120,519,2,5,53,1252,200,0,8,121}},
+ {"1600x1200-76",
+ {197980,1600,1200,10,44,120,519,2,7,50,1249,200,0,8,121}},
+ {"\0", },
+};
+
+static const char permedia2_name[16]="Permedia2";
+
+static struct pm2fb_info {
+ struct fb_info_gen gen;
+ int board; /* Permedia2 board index (see
+ board_table[] below) */
+ struct {
+ unsigned char* fb_base; /* framebuffer memory base */
+ unsigned long fb_size; /* framebuffer memory size */
+ unsigned char* rg_base; /* register memory base */
+ unsigned char* p_fb; /* physical address of frame buffer */
+ unsigned char* v_fb; /* virtual address of frame buffer */
+ unsigned char* p_regs; /* physical address of registers
+ region, must be rg_base or
+ rg_base+PM2_REGS_SIZE depending on
+ the host endianness */
+ unsigned char* v_regs; /* virtual address of p_regs */
+ } regions;
+ union { /* here, the per-board par structs */
+#ifdef CONFIG_FB_PM2_CVPPC
+ struct cvppc_par cvppc; /* CVisionPPC data */
+#endif
+ } board_par;
+ struct pm2fb_par current_par; /* displayed screen */
+ int current_par_valid;
+ unsigned long memclock; /* memclock (set by the per-board
+ init routine) */
+ struct display disp;
+ struct {
+ u8 transp;
+ u8 red;
+ u8 green;
+ u8 blue;
+ } palette[256];
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cmap16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cmap24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cmap32[16];
+#endif
+ } cmap;
+} fb_info;
+
+#ifdef CONFIG_FB_PM2_CVPPC
+static int cvppc_detect(struct pm2fb_info*);
+static void cvppc_init(struct pm2fb_info*);
+#endif
+
+/*
+ * Table of the supported Permedia2 based boards.
+ * Three hooks are defined for each board:
+ * detect(): should return 1 if the related board has been detected, 0
+ * otherwise. It should also fill the fields 'regions.fb_base',
+ * 'regions.fb_size', 'regions.rg_base' and 'memclock' in the
+ * passed pm2fb_info structure.
+ * init(): called immediately after the reset of the Permedia2 chip.
+ * It should reset the memory controller if needed (the MClk
+ * is set shortly afterwards by the caller).
+ * cleanup(): called after the driver has been unregistered.
+ *
+ * the init and cleanup pointers can be NULL.
+ */
+static const struct {
+ int (*detect)(struct pm2fb_info*);
+ void (*init)(struct pm2fb_info*);
+ void (*cleanup)(struct pm2fb_info*);
+ char name[32];
+} board_table[] = {
+#ifdef CONFIG_FB_PM2_CVPPC
+ { cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" },
+#endif
+ { NULL, }
+};
+
+/*
+ * partial products for the supported horizontal resolutions.
+ */
+#define PACKPP(p0,p1,p2) (((p2)<<6)|((p1)<<3)|(p0))
+static const struct {
+ unsigned short width;
+ unsigned short pp;
+} pp_table[] = {
+ { 32, PACKPP(1, 0, 0) }, { 64, PACKPP(1, 1, 0) },
+ { 96, PACKPP(1, 1, 1) }, { 128, PACKPP(2, 1, 1) },
+ { 160, PACKPP(2, 2, 1) }, { 192, PACKPP(2, 2, 2) },
+ { 224, PACKPP(3, 2, 1) }, { 256, PACKPP(3, 2, 2) },
+ { 288, PACKPP(3, 3, 1) }, { 320, PACKPP(3, 3, 2) },
+ { 384, PACKPP(3, 3, 3) }, { 416, PACKPP(4, 3, 1) },
+ { 448, PACKPP(4, 3, 2) }, { 512, PACKPP(4, 3, 3) },
+ { 544, PACKPP(4, 4, 1) }, { 576, PACKPP(4, 4, 2) },
+ { 640, PACKPP(4, 4, 3) }, { 768, PACKPP(4, 4, 4) },
+ { 800, PACKPP(5, 4, 1) }, { 832, PACKPP(5, 4, 2) },
+ { 896, PACKPP(5, 4, 3) }, { 1024, PACKPP(5, 4, 4) },
+ { 1056, PACKPP(5, 5, 1) }, { 1088, PACKPP(5, 5, 2) },
+ { 1152, PACKPP(5, 5, 3) }, { 1280, PACKPP(5, 5, 4) },
+ { 1536, PACKPP(5, 5, 5) }, { 1568, PACKPP(6, 5, 1) },
+ { 1600, PACKPP(6, 5, 2) }, { 1664, PACKPP(6, 5, 3) },
+ { 1792, PACKPP(6, 5, 4) }, { 2048, PACKPP(6, 5, 5) },
+ { 0, 0 } };
+
+static void pm2fb_detect(void);
+static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
+ const void* par, struct fb_info_gen* info);
+static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
+ void* par, struct fb_info_gen* info);
+static int pm2fb_encode_var(struct fb_var_screeninfo* var,
+ const void* par, struct fb_info_gen* info);
+static void pm2fb_get_par(void* par, struct fb_info_gen* info);
+static void pm2fb_set_par(const void* par, struct fb_info_gen* info);
+static int pm2fb_getcolreg(unsigned regno,
+ unsigned* red, unsigned* green, unsigned* blue,
+ unsigned* transp, struct fb_info* info);
+static int pm2fb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info* info);
+static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);
+static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
+ struct fb_info_gen* info);
+static void pm2fb_dispsw(const void* par, struct display* disp,
+ struct fb_info_gen* info);
+
+static struct fbgen_hwswitch pm2fb_hwswitch={
+ pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var,
+ pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par,
+ pm2fb_getcolreg, pm2fb_setcolreg, pm2fb_pan_display,
+ pm2fb_blank, pm2fb_dispsw
+};
+
+static int pm2fb_open(struct fb_info* info, int user);
+static int pm2fb_release(struct fb_info* info, int user);
+
+static struct fb_ops pm2fb_ops={
+ pm2fb_open, pm2fb_release, fbgen_get_fix, fbgen_get_var,
+ fbgen_set_var, fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display,
+ NULL /* fb_ioctl() */, NULL /* fb_mmap() */
+};
+
+/***************************************************************************
+ * Begin of Permedia2 specific functions
+ ***************************************************************************/
+
+inline static unsigned long RD32(unsigned char* base, long off) {
+
+ return *((volatile unsigned long* )(base+off));
+}
+
+inline static void WR32(unsigned char* base, long off, unsigned long v) {
+
+ *((volatile unsigned long* )(base+off))=v;
+}
+
+inline static unsigned long pm2_RD(struct pm2fb_info* p, long off) {
+
+ return RD32(p->regions.v_regs, off);
+}
+
+inline static void pm2_WR(struct pm2fb_info* p, long off, unsigned long v) {
+
+ WR32(p->regions.v_regs, off, v);
+}
+
+inline static unsigned long pm2_RDAC_RD(struct pm2fb_info* p, long idx) {
+
+ pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+ eieio();
+ return pm2_RD(p, PM2R_RD_INDEXED_DATA);
+}
+
+inline static void pm2_RDAC_WR(struct pm2fb_info* p, long idx,
+ unsigned long v) {
+
+ pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+ eieio();
+ pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
+}
+
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+#define WAIT_FIFO(p,a)
+#else
+inline static void WAIT_FIFO(struct pm2fb_info* p, unsigned long a) {
+
+ while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a);
+ eieio();
+}
+#endif
+
+static unsigned long partprod(unsigned long xres) {
+ int i;
+
+ for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++);
+ if (!pp_table[i].width)
+ DPRINTK("invalid width %lu\n", xres);
+ return pp_table[i].pp;
+}
+
+static unsigned long to3264(unsigned long timing, int bpp, int is64) {
+
+ switch (bpp) {
+ case 8:
+ timing=timing>>(2+is64);
+ break;
+ case 16:
+ timing=timing>>(1+is64);
+ break;
+ case 24:
+ timing=(timing*3)>>(2+is64);
+ break;
+ case 32:
+ if (is64)
+ timing=timing>>1;
+ break;
+ }
+ return timing;
+}
+
+static unsigned long from3264(unsigned long timing, int bpp, int is64) {
+
+ switch (bpp) {
+ case 8:
+ timing=timing<<(2+is64);
+ break;
+ case 16:
+ timing=timing<<(1+is64);
+ break;
+ case 24:
+ timing=(timing<<(2+is64))/3;
+ break;
+ case 32:
+ if (is64)
+ timing=timing<<1;
+ break;
+ }
+ return timing;
+}
+
+static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn,
+ unsigned char* pp) {
+ unsigned char m;
+ unsigned char n;
+ unsigned char p;
+ unsigned long f;
+ long current;
+ long delta=100000;
+
+ *mm=*nn=*pp=0;
+ for (n=2; n<15; n++) {
+ for (m=2; m; m++) {
+ f=PM2_REFERENCE_CLOCK*m/n;
+ if (f>=150000 && f<=300000) {
+ for (p=0; p<5; p++, f>>=1) {
+ current=clk>f?clk-f:f-clk;
+ if (current<delta) {
+ delta=current;
+ *mm=m;
+ *nn=n;
+ *pp=p;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void wait_pm2(struct pm2fb_info* i) {
+
+ WAIT_FIFO(i, 1);
+ pm2_WR(i, PM2R_SYNC, 0);
+ eieio();
+ do {
+ while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0);
+ eieio();
+ } while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));
+}
+
+static void set_memclock(struct pm2fb_info* info, unsigned long clk) {
+ int i;
+ unsigned char m, n, p;
+
+ mnp(clk, &m, &n, &p);
+ WAIT_FIFO(info, 5);
+ pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6);
+ eieio();
+ pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m);
+ pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n);
+ eieio();
+ pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p);
+ eieio();
+ pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS);
+ eieio();
+ for (i=256; i &&
+ !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
+}
+
+static void set_pixclock(struct pm2fb_info* info, unsigned long clk) {
+ int i;
+ unsigned char m, n, p;
+
+ mnp(clk, &m, &n, &p);
+ WAIT_FIFO(info, 5);
+ pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
+ eieio();
+ pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
+ pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n);
+ eieio();
+ pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
+ eieio();
+ pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
+ eieio();
+ for (i=256; i &&
+ !(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
+}
+
+static void set_color(struct pm2fb_info* p, unsigned char regno,
+ unsigned char r, unsigned char g, unsigned char b) {
+
+ WAIT_FIFO(p, 4);
+ eieio();
+ pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
+ eieio();
+ pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
+ eieio();
+ pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
+ eieio();
+ pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
+}
+
+static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) {
+
+ WAIT_FIFO(i, 2);
+#ifdef __LITTLE_ENDIAN
+ pm2_WR(i, PM2R_APERTURE_ONE, 0); /* FIXME */
+ pm2_WR(i, PM2R_APERTURE_TWO, 0);
+#else
+ switch (p->depth) {
+ case 8:
+ case 24:
+ pm2_WR(i, PM2R_APERTURE_ONE, 0);
+ pm2_WR(i, PM2R_APERTURE_TWO, 1);
+ break;
+ case 16:
+ pm2_WR(i, PM2R_APERTURE_ONE, 2);
+ pm2_WR(i, PM2R_APERTURE_TWO, 1);
+ break;
+ case 32:
+ pm2_WR(i, PM2R_APERTURE_ONE, 1);
+ pm2_WR(i, PM2R_APERTURE_TWO, 1);
+ break;
+ }
+#endif
+}
+
+static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
+ unsigned long clrmode=0;
+ unsigned long txtmap=0;
+ unsigned long xres;
+
+ xres=(p->width+31)&~31;
+ set_aperture(i, p);
+ WAIT_FIFO(i, 22);
+ pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0:
+ PM2F_COLOR_KEY_TEST_OFF);
+ switch (p->depth) {
+ case 8:
+ pm2_WR(i, PM2R_FB_READ_PIXEL, 0);
+ break;
+ case 16:
+ pm2_WR(i, PM2R_FB_READ_PIXEL, 1);
+ clrmode=PM2F_RD_TRUECOLOR|0x06;
+ txtmap=PM2F_TEXTEL_SIZE_16;
+ break;
+ case 32:
+ pm2_WR(i, PM2R_FB_READ_PIXEL, 2);
+ clrmode=PM2F_RD_TRUECOLOR|0x08;
+ txtmap=PM2F_TEXTEL_SIZE_32;
+ break;
+ case 24:
+ pm2_WR(i, PM2R_FB_READ_PIXEL, 4);
+ clrmode=PM2F_RD_TRUECOLOR|0x09;
+ txtmap=PM2F_TEXTEL_SIZE_24;
+ break;
+ }
+ pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width);
+ pm2_WR(i, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
+ pm2_WR(i, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
+ pm2_WR(i, PM2R_FB_READ_MODE, partprod(xres));
+ pm2_WR(i, PM2R_LB_READ_MODE, partprod(xres));
+ pm2_WR(i, PM2R_TEXTURE_MAP_FORMAT, txtmap|partprod(xres));
+ pm2_WR(i, PM2R_H_TOTAL, p->htotal);
+ pm2_WR(i, PM2R_HS_START, p->hsstart);
+ pm2_WR(i, PM2R_HS_END, p->hsend);
+ pm2_WR(i, PM2R_HG_END, p->hbend);
+ pm2_WR(i, PM2R_HB_END, p->hbend);
+ pm2_WR(i, PM2R_V_TOTAL, p->vtotal);
+ pm2_WR(i, PM2R_VS_START, p->vsstart);
+ pm2_WR(i, PM2R_VS_END, p->vsend);
+ pm2_WR(i, PM2R_VB_END, p->vbend);
+ pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
+ eieio();
+ pm2_WR(i, PM2R_SCREEN_BASE, p->base);
+ pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
+ PM2F_RD_GUI_ACTIVE|clrmode);
+ pm2_WR(i, PM2R_VIDEO_CONTROL, p->video);
+ set_pixclock(i, p->pixclock);
+};
+
+/***************************************************************************
+ * Begin of generic initialization functions
+ ***************************************************************************/
+
+static void pm2fb_reset(struct pm2fb_info* p) {
+
+ pm2_WR(p, PM2R_RESET_STATUS, 0);
+ eieio();
+ while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
+ eieio();
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+ DPRINTK("FIFO disconnect enabled\n");
+ pm2_WR(p, PM2R_FIFO_DISCON, 1);
+#endif
+ eieio();
+ if (board_table[p->board].init)
+ board_table[p->board].init(p);
+ WAIT_FIFO(p, 48);
+ pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
+ ~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
+ pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
+ pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
+ pm2_WR(p, PM2R_FIFO_CONTROL, 0);
+ pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
+ pm2_WR(p, PM2R_APERTURE_ONE, 0);
+ pm2_WR(p, PM2R_APERTURE_TWO, 0);
+ pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
+ pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0);
+ pm2_WR(p, PM2R_LB_READ_MODE, 0);
+ pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
+ pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
+ pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
+ pm2_WR(p, PM2R_WINDOW_ORIGIN, 0);
+ pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
+ pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
+ pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
+ pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
+ pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
+ pm2_WR(p, PM2R_DITHER_MODE, 0);
+ pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
+ pm2_WR(p, PM2R_DEPTH_MODE, 0);
+ pm2_WR(p, PM2R_STENCIL_MODE, 0);
+ pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
+ pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
+ pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
+ pm2_WR(p, PM2R_YUV_MODE, 0);
+ pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
+ pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
+ pm2_WR(p, PM2R_FOG_MODE, 0);
+ pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
+ pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
+ pm2_WR(p, PM2R_STATISTICS_MODE, 0);
+ pm2_WR(p, PM2R_SCISSOR_MODE, 0);
+ pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
+ pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
+ pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
+ pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
+ pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
+ pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
+ pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
+ eieio();
+ set_memclock(p, p->memclock);
+}
+
+__initfunc(static int pm2fb_conf(struct pm2fb_info* p)) {
+
+ for (p->board=0; board_table[p->board].detect &&
+ !(board_table[p->board].detect(p)); p->board++);
+ if (!board_table[p->board].detect) {
+ DPRINTK("no board found.\n");
+ return 0;
+ }
+ DPRINTK("found board: %s\n", board_table[p->board].name);
+ p->regions.p_fb=p->regions.fb_base;
+ p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size);
+#ifdef __LITTLE_ENDIAN
+ p->regions.p_regs=p->regions.rg_base;
+#else
+ p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
+#endif
+ p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE);
+ return 1;
+}
+
+/***************************************************************************
+ * Begin of per-board initialization functions
+ ***************************************************************************/
+
+#ifdef CONFIG_FB_PM2_CVPPC
+static int cvppc_PCI_init(struct cvppc_par* p) {
+ extern unsigned long powerup_PCI_present;
+
+ if (!powerup_PCI_present) {
+ DPRINTK("no PCI bridge detected\n");
+ return 0;
+ }
+ if (!(p->pci_config=MMAP(CVPPC_PCI_CONFIG, 256))) {
+ DPRINTK("unable to map PCI config region\n");
+ return 0;
+ }
+ if (RD32(p->pci_config, PCI_VENDOR_ID)!=
+ ((PCI_DEVICE_ID_TI_TVP4020<<16)|PCI_VENDOR_ID_TI)) {
+ DPRINTK("bad vendorID/deviceID\n");
+ return 0;
+ }
+ if (!(p->pci_bridge=MMAP(CSPPC_PCI_BRIDGE, 256))) {
+ DPRINTK("unable to map PCI bridge\n");
+ return 0;
+ }
+ WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN);
+ eieio();
+ if (pm2fb_options.flags & OPTF_OLD_MEM)
+ WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00);
+ WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION);
+ WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE);
+ WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO);
+ WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS);
+ eieio();
+ WR32(p->pci_config, PCI_COMMAND, 0xef000000 |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ return 1;
+}
+
+static int cvppc_detect(struct pm2fb_info* p) {
+
+ if (!cvppc_PCI_init(&p->board_par.cvppc))
+ return 0;
+ p->regions.fb_base=(unsigned char* )CVPPC_FB_APERTURE_ONE;
+ p->regions.fb_size=CVPPC_FB_SIZE;
+ p->regions.rg_base=(unsigned char* )CVPPC_REGS_REGION;
+ p->memclock=CVPPC_MEMCLOCK;
+ return 1;
+}
+
+static void cvppc_init(struct pm2fb_info* p) {
+
+ WAIT_FIFO(p, 3);
+ pm2_WR(p, PM2R_MEM_CONTROL, 0);
+ pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30);
+ eieio();
+ if (pm2fb_options.flags & OPTF_OLD_MEM)
+ pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD);
+ else
+ pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_NEW);
+}
+#endif /* CONFIG_FB_PM2_CVPPC */
+
+/***************************************************************************
+ * Console hw acceleration
+ ***************************************************************************/
+
+/*
+ * copy with packed pixels (8/16bpp only).
+ */
+static void pm2fb_pp_copy(struct pm2fb_info* i, long xsrc, long ysrc,
+ long x, long y, long w, long h) {
+ long scale=i->current_par.depth==8?2:1;
+ long offset;
+
+ if (!w || !h)
+ return;
+ WAIT_FIFO(i, 7);
+ pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
+ PM2F_CONFIG_FB_PACKED_DATA|
+ PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+ pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+ pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
+ ((xsrc-x)&0xfff));
+ offset=(x&0x3)-(xsrc&0x3);
+ pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
+ pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
+ pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
+ eieio();
+ pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE|
+ (x<xsrc?PM2F_INCREASE_X:0)|
+ (y<ysrc?PM2F_INCREASE_Y:0));
+ wait_pm2(i);
+}
+
+/*
+ * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
+ */
+static void pm2fb_block_op(struct pm2fb_info* i, int copy,
+ long xsrc, long ysrc,
+ long x, long y, long w, long h,
+ unsigned long color) {
+
+ if (!w || !h)
+ return;
+ WAIT_FIFO(i, 6);
+ pm2_WR(i, PM2R_CONFIG, PM2F_CONFIG_FB_WRITE_ENABLE|
+ PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+ pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+ if (copy)
+ pm2_WR(i, PM2R_FB_SOURCE_DELTA, ((ysrc-y)&0xfff)<<16|
+ ((xsrc-x)&0xfff));
+ else
+ pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
+ pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
+ pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
+ eieio();
+ pm2_WR(i, PM2R_RENDER, PM2F_RENDER_RECTANGLE|
+ (x<xsrc?PM2F_INCREASE_X:0)|
+ (y<ysrc?PM2F_INCREASE_Y:0)|
+ (copy?0:PM2F_RENDER_FASTFILL));
+ wait_pm2(i);
+}
+
+static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+ unsigned long video;
+
+ if (!i->current_par_valid)
+ return 1;
+ video=i->current_par.video;
+ if (blank_mode>0) {
+ switch (blank_mode-1) {
+ case VESA_NO_BLANKING: /* FIXME */
+ video=video&~(PM2F_VIDEO_ENABLE);
+ break;
+ case VESA_HSYNC_SUSPEND:
+ video=video&~(PM2F_HSYNC_MASK|
+ PM2F_BLANK_LOW);
+ break;
+ case VESA_VSYNC_SUSPEND:
+ video=video&~(PM2F_VSYNC_MASK|
+ PM2F_BLANK_LOW);
+ break;
+ case VESA_POWERDOWN:
+ video=video&~(PM2F_VSYNC_MASK|
+ PM2F_HSYNC_MASK|
+ PM2F_BLANK_LOW);
+ break;
+ }
+ }
+ WAIT_FIFO(i, 1);
+ pm2_WR(i, PM2R_VIDEO_CONTROL, video);
+ return 0;
+}
+
+static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
+ struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+ if (!i->current_par_valid)
+ return -EINVAL;
+ i->current_par.base=to3264(var->yoffset*i->current_par.width+
+ var->xoffset, i->current_par.depth, 1);
+ WAIT_FIFO(i, 1);
+ pm2_WR(i, PM2R_SCREEN_BASE, i->current_par.base);
+ return 0;
+}
+
+static void pm2fb_pp_bmove(struct display* p, int sy, int sx,
+ int dy, int dx, int height, int width) {
+
+ if (fontwidthlog(p)) {
+ sx=sx<<fontwidthlog(p);
+ dx=dx<<fontwidthlog(p);
+ width=width<<fontwidthlog(p);
+ }
+ else {
+ sx=sx*fontwidth(p);
+ dx=dx*fontwidth(p);
+ width=width*fontwidth(p);
+ }
+ sy=sy*fontheight(p);
+ dy=dy*fontheight(p);
+ height=height*fontheight(p);
+ pm2fb_pp_copy((struct pm2fb_info* )p->fb_info, sx, sy, dx,
+ dy, width, height);
+}
+
+static void pm2fb_bmove(struct display* p, int sy, int sx,
+ int dy, int dx, int height, int width) {
+
+ if (fontwidthlog(p)) {
+ sx=sx<<fontwidthlog(p);
+ dx=dx<<fontwidthlog(p);
+ width=width<<fontwidthlog(p);
+ }
+ else {
+ sx=sx*fontwidth(p);
+ dx=dx*fontwidth(p);
+ width=width*fontwidth(p);
+ }
+ sy=sy*fontheight(p);
+ dy=dy*fontheight(p);
+ height=height*fontheight(p);
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 1, sx, sy, dx, dy,
+ width, height, 0);
+}
+
+#ifdef FBCON_HAS_CFB8
+static void pm2fb_clear8(struct vc_data* conp, struct display* p,
+ int sy, int sx, int height, int width) {
+ unsigned long c;
+
+ sx=sx*fontwidth(p);
+ width=width*fontwidth(p);
+ sy=sy*fontheight(p);
+ height=height*fontheight(p);
+ c=attr_bgcol_ec(p, conp);
+ c|=c<<8;
+ c|=c<<16;
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
+ width, height, c);
+}
+
+static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p,
+ int bottom_only) {
+ unsigned long c;
+ unsigned long sx;
+ unsigned long sy;
+
+ c=attr_bgcol_ec(p, conp);
+ c|=c<<8;
+ c|=c<<16;
+ sx=conp->vc_cols*fontwidth(p);
+ sy=conp->vc_rows*fontheight(p);
+ if (!bottom_only)
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+ sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+ 0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
+}
+
+static struct display_switch pm2_cfb8 = {
+ fbcon_cfb8_setup, pm2fb_pp_bmove, pm2fb_clear8,
+ fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc,
+ NULL /* cursor() */, NULL /* set_font() */,
+ pm2fb_clear_margins8,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB8 */
+
+#ifdef FBCON_HAS_CFB16
+static void pm2fb_clear16(struct vc_data* conp, struct display* p,
+ int sy, int sx, int height, int width) {
+ unsigned long c;
+
+ sx=sx*fontwidth(p);
+ width=width*fontwidth(p);
+ sy=sy*fontheight(p);
+ height=height*fontheight(p);
+ c=((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ c|=c<<16;
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
+ width, height, c);
+}
+
+static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p,
+ int bottom_only) {
+ unsigned long c;
+ unsigned long sx;
+ unsigned long sy;
+
+ c = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ c|=c<<16;
+ sx=conp->vc_cols*fontwidth(p);
+ sy=conp->vc_rows*fontheight(p);
+ if (!bottom_only)
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+ sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+ 0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
+}
+
+static struct display_switch pm2_cfb16 = {
+ fbcon_cfb16_setup, pm2fb_pp_bmove, pm2fb_clear16,
+ fbcon_cfb16_putc, fbcon_cfb16_putcs, fbcon_cfb16_revc,
+ NULL /* cursor() */, NULL /* set_font() */,
+ pm2fb_clear_margins16,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB16 */
+
+#ifdef FBCON_HAS_CFB24
+/*
+ * fast fill for 24bpp works only when red==green==blue
+ */
+static void pm2fb_clear24(struct vc_data* conp, struct display* p,
+ int sy, int sx, int height, int width) {
+ struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
+ unsigned long c;
+
+ c=attr_bgcol_ec(p, conp);
+ if ( i->palette[c].red==i->palette[c].green &&
+ i->palette[c].green==i->palette[c].blue) {
+ c=((u32 *)p->dispsw_data)[c];
+ c|=(c&0xff0000)<<8;
+ sx=sx*fontwidth(p);
+ width=width*fontwidth(p);
+ sy=sy*fontheight(p);
+ height=height*fontheight(p);
+ pm2fb_block_op(i, 0, 0, 0, sx, sy, width, height, c);
+ }
+ else
+ fbcon_cfb24_clear(conp, p, sy, sx, height, width);
+
+}
+
+static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p,
+ int bottom_only) {
+ struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
+ unsigned long c;
+ unsigned long sx;
+ unsigned long sy;
+
+ c=attr_bgcol_ec(p, conp);
+ if ( i->palette[c].red==i->palette[c].green &&
+ i->palette[c].green==i->palette[c].blue) {
+ c=((u32 *)p->dispsw_data)[c];
+ c|=(c&0xff0000)<<8;
+ sx=conp->vc_cols*fontwidth(p);
+ sy=conp->vc_rows*fontheight(p);
+ if (!bottom_only)
+ pm2fb_block_op(i, 0, 0, 0, sx, 0, (p->var.xres-sx),
+ p->var.yres_virtual, c);
+ pm2fb_block_op(i, 0, 0, 0, 0, p->var.yoffset+sy,
+ sx, p->var.yres-sy, c);
+ }
+ else
+ fbcon_cfb24_clear_margins(conp, p, bottom_only);
+
+}
+
+static struct display_switch pm2_cfb24 = {
+ fbcon_cfb24_setup, pm2fb_bmove, pm2fb_clear24,
+ fbcon_cfb24_putc, fbcon_cfb24_putcs, fbcon_cfb24_revc,
+ NULL /* cursor() */, NULL /* set_font() */,
+ pm2fb_clear_margins24,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB24 */
+
+#ifdef FBCON_HAS_CFB32
+static void pm2fb_clear32(struct vc_data* conp, struct display* p,
+ int sy, int sx, int height, int width) {
+ unsigned long c;
+
+ sx=sx*fontwidth(p);
+ width=width*fontwidth(p);
+ sy=sy*fontheight(p);
+ height=height*fontheight(p);
+ c=((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
+ width, height, c);
+}
+
+static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p,
+ int bottom_only) {
+ unsigned long c;
+ unsigned long sx;
+ unsigned long sy;
+
+ c = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+ sx=conp->vc_cols*fontwidth(p);
+ sy=conp->vc_rows*fontheight(p);
+ if (!bottom_only)
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+ sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
+ pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+ 0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
+}
+
+static struct display_switch pm2_cfb32 = {
+ fbcon_cfb32_setup, pm2fb_bmove, pm2fb_clear32,
+ fbcon_cfb32_putc, fbcon_cfb32_putcs, fbcon_cfb32_revc,
+ NULL /* cursor() */, NULL /* set_font() */,
+ pm2fb_clear_margins32,
+ FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB32 */
+
+/***************************************************************************
+ * Framebuffer functions
+ ***************************************************************************/
+
+static void pm2fb_detect(void) {}
+
+static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
+ const void* par, struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+ struct pm2fb_par* p=(struct pm2fb_par* )par;
+
+ strcpy(fix->id, permedia2_name);
+ fix->smem_start=i->regions.p_fb;
+ fix->smem_len=i->regions.fb_size;
+ fix->mmio_start=i->regions.p_regs;
+ fix->mmio_len=PM2_REGS_SIZE;
+ fix->accel=FB_ACCEL_3DLABS_PERMEDIA2;
+ fix->type=FB_TYPE_PACKED_PIXELS;
+ fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
+ fix->line_length=0;
+ fix->xpanstep=p->depth==24?8:64/p->depth;
+ fix->ypanstep=1;
+ fix->ywrapstep=0;
+ return 0;
+}
+
+static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
+ void* par, struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+ struct pm2fb_par p;
+ unsigned long xres;
+ int data64;
+
+ memset(&p, 0, sizeof(struct pm2fb_par));
+ p.width=(var->xres_virtual+7)&~7;
+ p.height=var->yres_virtual;
+ p.depth=(var->bits_per_pixel+7)&~7;
+ p.depth=p.depth>32?32:p.depth;
+ data64=p.depth>8;
+ xres=(var->xres+31)&~31;
+ if (p.width==~(0L))
+ p.width=xres;
+ if (p.height==~(0L))
+ p.height=var->yres;
+ if (p.width<xres+var->xoffset)
+ p.width=xres+var->xoffset;
+ if (p.height<var->yres+var->yoffset)
+ p.height=var->yres+var->yoffset;
+ if (!partprod(xres)) {
+ DPRINTK("width not supported: %lu\n", xres);
+ return -EINVAL;
+ }
+ if (p.width>2047) {
+ DPRINTK("virtual width not supported: %lu\n", p.width);
+ return -EINVAL;
+ }
+ if (var->yres<200) {
+ DPRINTK("height not supported: %lu\n",
+ (unsigned long )var->yres);
+ return -EINVAL;
+ }
+ if (p.height<200 || p.height>2047) {
+ DPRINTK("virtual height not supported: %lu\n", p.height);
+ return -EINVAL;
+ }
+ if (p.width*p.height*p.depth/8>i->regions.fb_size) {
+ DPRINTK("no memory for screen (%lux%lux%lu)\n",
+ xres, p.height, p.depth);
+ return -EINVAL;
+ }
+ p.pixclock=PICOS2KHZ(var->pixclock);
+ if (p.pixclock>PM2_MAX_PIXCLOCK) {
+ DPRINTK("pixclock too high (%luKHz)\n", p.pixclock);
+ return -EINVAL;
+ }
+ p.hsstart=to3264(var->right_margin, p.depth, data64);
+ p.hsend=p.hsstart+to3264(var->hsync_len, p.depth, data64);
+ p.hbend=p.hsend+to3264(var->left_margin, p.depth, data64);
+ p.htotal=to3264(xres, p.depth, data64)+p.hbend-1;
+ p.vsstart=var->lower_margin?var->lower_margin-1:0; /* FIXME! */
+ p.vsend=var->lower_margin+var->vsync_len-1;
+ p.vbend=var->lower_margin+var->vsync_len+var->upper_margin;
+ p.vtotal=var->yres+p.vbend-1;
+ p.stride=to3264(p.width, p.depth, 1);
+ p.base=to3264(var->yoffset*xres+var->xoffset, p.depth, 1);
+ if (data64)
+ p.video|=PM2F_DATA_64_ENABLE;
+ if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+ p.video|=PM2F_HSYNC_ACT_HIGH;
+ else
+ p.video|=PM2F_HSYNC_ACT_LOW;
+ if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+ p.video|=PM2F_VSYNC_ACT_HIGH;
+ else
+ p.video|=PM2F_VSYNC_ACT_LOW;
+ if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
+ DPRINTK("interlaced not supported\n");
+ return -EINVAL;
+ }
+ if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
+ p.video|=PM2F_LINE_DOUBLE;
+ if (var->activate==FB_ACTIVATE_NOW)
+ p.video|=PM2F_VIDEO_ENABLE;
+ *((struct pm2fb_par* )par)=p;
+ return 0;
+}
+
+static int pm2fb_encode_var(struct fb_var_screeninfo* var,
+ const void* par, struct fb_info_gen* info) {
+ struct pm2fb_par* p=(struct pm2fb_par* )par;
+ struct fb_var_screeninfo v;
+ unsigned long base;
+
+ memset(&v, 0, sizeof(struct fb_var_screeninfo));
+ v.xres_virtual=p->width;
+ v.yres_virtual=p->height;
+ v.xres=(p->htotal+1)-p->hbend;
+ v.yres=(p->vtotal+1)-p->vbend;
+ v.right_margin=p->hsstart;
+ v.hsync_len=p->hsend-p->hsstart;
+ v.left_margin=p->hbend-p->hsend;
+ v.lower_margin=p->vsstart+1;
+ v.vsync_len=p->vsend-v.lower_margin+1;
+ v.upper_margin=p->vbend-v.lower_margin-v.vsync_len;
+ v.bits_per_pixel=p->depth;
+ if (p->video & PM2F_DATA_64_ENABLE) {
+ v.xres=v.xres<<1;
+ v.right_margin=v.right_margin<<1;
+ v.hsync_len=v.hsync_len<<1;
+ v.left_margin=v.left_margin<<1;
+ }
+ switch (p->depth) {
+ case 8:
+ v.red.length=v.green.length=v.blue.length=8;
+ v.xres=v.xres<<2;
+ v.right_margin=v.right_margin<<2;
+ v.hsync_len=v.hsync_len<<2;
+ v.left_margin=v.left_margin<<2;
+ break;
+ case 16:
+ v.red.offset=11;
+ v.red.length=5;
+ v.green.offset=5;
+ v.green.length=6;
+ v.blue.length=5;
+ v.xres=v.xres<<1;
+ v.right_margin=v.right_margin<<1;
+ v.hsync_len=v.hsync_len<<1;
+ v.left_margin=v.left_margin<<1;
+ break;
+ case 32:
+ v.transp.offset=24;
+ v.red.offset=16;
+ v.green.offset=8;
+ v.red.length=v.green.length=v.blue.length=
+ v.transp.length=8;
+ break;
+ case 24:
+ v.blue.offset=16;
+ v.green.offset=8;
+ v.red.length=v.green.length=v.blue.length=8;
+ v.xres=(v.xres<<2)/3;
+ v.right_margin=(v.right_margin<<2)/3;
+ v.hsync_len=(v.hsync_len<<2)/3;
+ v.left_margin=(v.left_margin<<2)/3;
+ break;
+ }
+ base=from3264(p->base, p->depth, 1);
+ v.xoffset=base%v.xres;
+ v.yoffset=base/v.xres;
+ v.height=v.width=-1;
+ v.pixclock=KHZ2PICOS(p->pixclock);
+ if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH)
+ v.sync|=FB_SYNC_HOR_HIGH_ACT;
+ if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH)
+ v.sync|=FB_SYNC_VERT_HIGH_ACT;
+ if (p->video & PM2F_LINE_DOUBLE)
+ v.vmode=FB_VMODE_DOUBLE;
+ *var=v;
+ return 0;
+}
+
+static void set_user_mode(struct pm2fb_info* i) {
+
+ memcpy(&i->current_par, &pm2fb_options.user_mode,
+ sizeof(i->current_par));
+ if (pm2fb_options.flags & OPTF_YPAN) {
+ i->current_par.height=i->regions.fb_size/
+ (i->current_par.width*i->current_par.depth/8);
+ i->current_par.height=MIN(i->current_par.height,2047);
+ i->current_par.height=MAX(i->current_par.height,
+ pm2fb_options.user_mode.height);
+ }
+}
+
+static void pm2fb_get_par(void* par, struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+ if (!i->current_par_valid) {
+ set_user_mode(i);
+ pm2fb_reset(i);
+ set_screen(i, &i->current_par);
+ i->current_par_valid=1;
+ }
+ *((struct pm2fb_par* )par)=i->current_par;
+}
+
+static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+ struct pm2fb_par* p;
+
+ p=(struct pm2fb_par* )par;
+ if (i->current_par_valid) {
+ i->current_par.base=p->base;
+ if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) {
+ WAIT_FIFO(i, 1);
+ pm2_WR(i, PM2R_SCREEN_BASE, p->base);
+ return;
+ }
+ }
+ i->current_par=*p;
+ i->current_par_valid=1;
+ set_screen(i, &i->current_par);
+}
+
+static int pm2fb_getcolreg(unsigned regno,
+ unsigned* red, unsigned* green, unsigned* blue,
+ unsigned* transp, struct fb_info* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+ if (regno<256) {
+ *red=i->palette[regno].red<<8|i->palette[regno].red;
+ *green=i->palette[regno].green<<8|i->palette[regno].green;
+ *blue=i->palette[regno].blue<<8|i->palette[regno].blue;
+ *transp=i->palette[regno].transp<<8|i->palette[regno].transp;
+ }
+ return regno>255;
+}
+
+static int pm2fb_setcolreg(unsigned regno,
+ unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+ if (regno<16) {
+ switch (i->current_par.depth) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ i->cmap.cmap16[regno]=
+ ((u32 )red & 0xf800) |
+ (((u32 )green & 0xfc00)>>5) |
+ (((u32 )blue & 0xf800)>>11);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ i->cmap.cmap24[regno]=
+ (((u32 )blue & 0xff00) << 8) |
+ ((u32 )green & 0xff00) |
+ (((u32 )red & 0xff00) >> 8);
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ i->cmap.cmap32[regno]=
+ (((u32 )transp & 0xff00) << 16) |
+ (((u32 )red & 0xff00) << 8) |
+ (((u32 )green & 0xff00)) |
+ (((u32 )blue & 0xff00) >> 8);
+ break;
+#endif
+ default:
+ DPRINTK("bad depth %lu\n",
+ i->current_par.depth);
+ break;
+ }
+ }
+ if (regno<256) {
+ i->palette[regno].red=red >> 8;
+ i->palette[regno].green=green >> 8;
+ i->palette[regno].blue=blue >> 8;
+ i->palette[regno].transp=transp >> 8;
+ if (i->current_par.depth==8)
+ set_color(i, regno, red>>8, green>>8, blue>>8);
+ }
+ return regno>255;
+}
+
+static void pm2fb_dispsw(const void* par, struct display* disp,
+ struct fb_info_gen* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+ unsigned long flags;
+ unsigned long depth;
+
+ save_flags(flags);
+ cli();
+ switch (depth=((struct pm2fb_par* )par)->depth) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ disp->dispsw=&pm2_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ disp->dispsw=&pm2_cfb16;
+ disp->dispsw_data=i->cmap.cmap16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ disp->dispsw=&pm2_cfb24;
+ disp->dispsw_data=i->cmap.cmap24;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ disp->dispsw=&pm2_cfb32;
+ disp->dispsw_data=i->cmap.cmap32;
+ break;
+#endif
+ default:
+ disp->dispsw=&fbcon_dummy;
+ break;
+ }
+ restore_flags(flags);
+}
+
+static int pm2fb_open(struct fb_info* info, int user) {
+
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int pm2fb_release(struct fb_info* info, int user) {
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+/***************************************************************************
+ * Begin of public functions
+ ***************************************************************************/
+
+void pm2fb_cleanup(struct fb_info* info) {
+ struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+ unregister_framebuffer(info);
+ pm2fb_reset(i);
+ /* FIXME UNMAP()??? */
+ if (board_table[i->board].cleanup)
+ board_table[i->board].cleanup(i);
+}
+
+__initfunc(void pm2fb_init(void)) {
+
+ memset(&fb_info, 0, sizeof(fb_info));
+ if (!pm2fb_conf(&fb_info))
+ return;
+ fb_info.disp.scrollmode=SCROLL_YNOMOVE;
+ fb_info.gen.parsize=sizeof(struct pm2fb_par);
+ fb_info.gen.fbhw=&pm2fb_hwswitch;
+ strcpy(fb_info.gen.info.modename, permedia2_name);
+ fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
+ fb_info.gen.info.fbops=&pm2fb_ops;
+ fb_info.gen.info.disp=&fb_info.disp;
+ strcpy(fb_info.gen.info.fontname, pm2fb_options.font);
+ fb_info.gen.info.switch_con=&fbgen_switch;
+ fb_info.gen.info.updatevar=&fbgen_update_var;
+ fb_info.gen.info.blank=&fbgen_blank;
+ fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
+ if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0)
+ return;
+ fbgen_set_disp(-1, &fb_info.gen);
+ fbgen_install_cmap(0, &fb_info.gen);
+ if (register_framebuffer(&fb_info.gen.info)<0) {
+ printk("pm2fb: unable to register.\n");
+ return;
+ }
+ printk("fb%d: %s (%s), using %ldK of video memory.\n",
+ GET_FB_IDX(fb_info.gen.info.node),
+ board_table[fb_info.board].name,
+ permedia2_name,
+ (unsigned long )(fb_info.regions.fb_size>>10));
+ MOD_INC_USE_COUNT;
+}
+
+__initfunc(void pm2fb_mode_setup(char* options)) {
+ int i;
+
+ for (i=0; user_mode[i].name[0] &&
+ strcmp(options, user_mode[i].name); i++);
+ if (user_mode[i].name[0])
+ memcpy(&pm2fb_options.user_mode, &user_mode[i].par,
+ sizeof(pm2fb_options.user_mode));
+}
+
+__initfunc(void pm2fb_font_setup(char* options)) {
+
+ strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));
+ pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';
+}
+
+__initfunc(void pm2fb_setup(char* options, int* ints)) {
+ char* next;
+
+ memset(&pm2fb_options, 0, sizeof(pm2fb_options));
+ memcpy(&pm2fb_options.user_mode, &user_mode[0].par,
+ sizeof(pm2fb_options.user_mode));
+ while (options) {
+ if ((next=strchr(options, ',')))
+ *(next++)='\0';
+ if (!strncmp(options, "font:", 5))
+ pm2fb_font_setup(options+5);
+ else if (!strncmp(options, "mode:", 5))
+ pm2fb_mode_setup(options+5);
+ else if (!strcmp(options, "ypan"))
+ pm2fb_options.flags |= OPTF_YPAN;
+ else if (!strcmp(options, "oldmem"))
+ pm2fb_options.flags |= OPTF_OLD_MEM;
+ options=next;
+ }
+}
+
+/***************************************************************************
+ * Begin of module functions
+ ***************************************************************************/
+
+#ifdef MODULE
+int init_module(void) {
+
+ pm2fb_init();
+}
+
+void cleanup_module(void) {
+
+ pm2fb_cleanup();
+}
+#endif /* MODULE */
+
+/***************************************************************************
+ * That's all folks!
+ ***************************************************************************/
diff --git a/drivers/video/pm2fb.h b/drivers/video/pm2fb.h
new file mode 100644
index 000000000..94f346427
--- /dev/null
+++ b/drivers/video/pm2fb.h
@@ -0,0 +1,181 @@
+/*
+ * Permedia2 framebuffer driver definitions.
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * $Id: pm2fb.h,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef PM2FB_H
+#define PM2FB_H
+
+#define PM2_REFERENCE_CLOCK 14318 /* in KHz */
+#define PM2_MAX_PIXCLOCK 230000 /* in KHz */
+#define PM2_REGS_SIZE 0x10000
+
+#define PM2TAG(r) (unsigned long )(((r)-0x8000)>>3)
+
+/*****************************************************************************
+ * Permedia2 registers used in the framebuffer
+ *****************************************************************************/
+
+#define PM2R_RESET_STATUS 0x0000
+#define PM2R_IN_FIFO_SPACE 0x0018
+#define PM2R_OUT_FIFO_WORDS 0x0020
+#define PM2R_APERTURE_ONE 0x0050
+#define PM2R_APERTURE_TWO 0x0058
+#define PM2R_FIFO_DISCON 0x0068
+#define PM2R_CHIP_CONFIG 0x0070
+
+#define PM2R_REBOOT 0x1000
+#define PM2R_MEM_CONTROL 0x1040
+#define PM2R_BOOT_ADDRESS 0x1080
+#define PM2R_MEM_CONFIG 0x10c0
+#define PM2R_BYPASS_WRITE_MASK 0x1100
+#define PM2R_FRAMEBUFFER_WRITE_MASK 0x1140
+
+#define PM2R_OUT_FIFO 0x2000
+
+#define PM2R_SCREEN_BASE 0x3000
+#define PM2R_SCREEN_STRIDE 0x3008
+#define PM2R_H_TOTAL 0x3010
+#define PM2R_HG_END 0x3018
+#define PM2R_HB_END 0x3020
+#define PM2R_HS_START 0x3028
+#define PM2R_HS_END 0x3030
+#define PM2R_V_TOTAL 0x3038
+#define PM2R_VB_END 0x3040
+#define PM2R_VS_START 0x3048
+#define PM2R_VS_END 0x3050
+#define PM2R_VIDEO_CONTROL 0x3058
+#define PM2R_LINE_COUNT 0x3070
+#define PM2R_FIFO_CONTROL 0x3078
+
+#define PM2R_RD_PALETTE_WRITE_ADDRESS 0x4000
+#define PM2R_RD_PALETTE_DATA 0x4008
+#define PM2R_RD_PALETTE_READ_ADDRESS 0x4018
+#define PM2R_RD_INDEXED_DATA 0x4050
+
+#define PM2R_START_X_DOM 0x8000
+#define PM2R_D_X_DOM 0x8008
+#define PM2R_START_X_SUB 0x8010
+#define PM2R_D_X_SUB 0x8018
+#define PM2R_START_Y 0x8020
+#define PM2R_D_Y 0x8028
+#define PM2R_COUNT 0x8030
+#define PM2R_RENDER 0x8038
+#define PM2R_RECTANGLE_ORIGIN 0x80d0
+#define PM2R_RECTANGLE_SIZE 0x80d8
+#define PM2R_PACKED_DATA_LIMITS 0x8150
+#define PM2R_SCISSOR_MODE 0x8180
+#define PM2R_SCREEN_SIZE 0x8198
+#define PM2R_AREA_STIPPLE_MODE 0x81a0
+#define PM2R_WINDOW_ORIGIN 0x81c8
+#define PM2R_TEXTURE_ADDRESS_MODE 0x8380
+#define PM2R_TEXTURE_MAP_FORMAT 0x8588
+#define PM2R_TEXTURE_DATA_FORMAT 0x8590
+#define PM2R_TEXTURE_READ_MODE 0x8670
+#define PM2R_TEXEL_LUT_MODE 0x8678
+#define PM2R_TEXTURE_COLOR_MODE 0x8680
+#define PM2R_FOG_MODE 0x8690
+#define PM2R_COLOR_DDA_MODE 0x87e0
+#define PM2R_ALPHA_BLEND_MODE 0x8810
+#define PM2R_DITHER_MODE 0x8818
+#define PM2R_FB_SOFT_WRITE_MASK 0x8820
+#define PM2R_LOGICAL_OP_MODE 0x8828
+#define PM2R_LB_READ_MODE 0x8880
+#define PM2R_LB_READ_FORMAT 0x8888
+#define PM2R_LB_SOURCE_OFFSET 0x8890
+#define PM2R_LB_WINDOW_BASE 0x88b8
+#define PM2R_LB_WRITE_FORMAT 0x88c8
+#define PM2R_STENCIL_MODE 0x8988
+#define PM2R_DEPTH_MODE 0x89a0
+#define PM2R_FB_READ_MODE 0x8a80
+#define PM2R_FB_SOURCE_OFFSET 0x8a88
+#define PM2R_FB_PIXEL_OFFSET 0x8a90
+#define PM2R_FB_WINDOW_BASE 0x8ab0
+#define PM2R_FB_WRITE_MODE 0x8ab8
+#define PM2R_FB_HARD_WRITE_MASK 0x8ac0
+#define PM2R_FB_BLOCK_COLOR 0x8ac8
+#define PM2R_FB_READ_PIXEL 0x8ad0
+#define PM2R_FILTER_MODE 0x8c00
+#define PM2R_SYNC 0x8c40
+#define PM2R_YUV_MODE 0x8f00
+#define PM2R_STATISTICS_MODE 0x8c08
+#define PM2R_FB_SOURCE_DELTA 0x8d88
+#define PM2R_CONFIG 0x8d90
+
+/* Permedia2 RAMDAC indexed registers */
+#define PM2I_RD_CURSOR_CONTROL 0x06
+#define PM2I_RD_COLOR_MODE 0x18
+#define PM2I_RD_MODE_CONTROL 0x19
+#define PM2I_RD_MISC_CONTROL 0x1e
+#define PM2I_RD_PIXEL_CLOCK_A1 0x20
+#define PM2I_RD_PIXEL_CLOCK_A2 0x21
+#define PM2I_RD_PIXEL_CLOCK_A3 0x22
+#define PM2I_RD_PIXEL_CLOCK_STATUS 0x29
+#define PM2I_RD_MEMORY_CLOCK_1 0x30
+#define PM2I_RD_MEMORY_CLOCK_2 0x31
+#define PM2I_RD_MEMORY_CLOCK_3 0x32
+#define PM2I_RD_MEMORY_CLOCK_STATUS 0x33
+#define PM2I_RD_COLOR_KEY_CONTROL 0x40
+#define PM2I_RD_OVERLAY_KEY 0x41
+#define PM2I_RD_RED_KEY 0x42
+#define PM2I_RD_GREEN_KEY 0x43
+#define PM2I_RD_BLUE_KEY 0x44
+
+/* Fields and flags */
+#define PM2F_RENDER_AREASTIPPLE (1<<0)
+#define PM2F_RENDER_FASTFILL (1<<3)
+#define PM2F_RENDER_PRIMITIVE_MASK (0x3<<6)
+#define PM2F_RENDER_LINE 0
+#define PM2F_RENDER_TRAPEZOID (1<<6)
+#define PM2F_RENDER_POINT (2<<6)
+#define PM2F_RENDER_RECTANGLE (3<<6)
+#define PM2F_SYNCHRONIZATION (1<<10)
+#define PM2F_PLL_LOCKED 0x10
+#define PM2F_BEING_RESET (1<<31)
+#define PM2F_DATATYPE_COLOR 0x8000
+#define PM2F_VGA_ENABLE 0x02
+#define PM2F_VGA_FIXED 0x04
+#define PM2F_FB_WRITE_ENABLE 0x01
+#define PM2F_FB_READ_SOURCE_ENABLE 0x0200
+#define PM2F_RD_PALETTE_WIDTH_8 0x02
+#define PM2F_PART_PROD_MASK 0x01ff
+#define PM2F_SCREEN_SCISSOR_ENABLE 0x02
+#define PM2F_DATA_64_ENABLE 0x00010000
+#define PM2F_BLANK_LOW 0x02
+#define PM2F_HSYNC_MASK 0x18
+#define PM2F_VSYNC_MASK 0x60
+#define PM2F_HSYNC_ACT_HIGH 0x08
+#define PM2F_HSYNC_FORCED_LOW 0x10
+#define PM2F_HSYNC_ACT_LOW 0x18
+#define PM2F_VSYNC_ACT_HIGH 0x20
+#define PM2F_VSYNC_FORCED_LOW 0x40
+#define PM2F_VSYNC_ACT_LOW 0x60
+#define PM2F_LINE_DOUBLE 0x04
+#define PM2F_VIDEO_ENABLE 0x01
+#define PM2F_RD_GUI_ACTIVE 0x10
+#define PM2F_RD_COLOR_MODE_RGB 0x20
+#define PM2F_RD_TRUECOLOR 0x80
+#define PM2F_NO_ALPHA_BUFFER 0x10
+#define PM2F_TEXTEL_SIZE_16 0x00080000
+#define PM2F_TEXTEL_SIZE_32 0x00100000
+#define PM2F_TEXTEL_SIZE_4 0x00180000
+#define PM2F_TEXTEL_SIZE_24 0x00200000
+#define PM2F_INCREASE_X (1<<21)
+#define PM2F_INCREASE_Y (1<<22)
+#define PM2F_CONFIG_FB_WRITE_ENABLE (1<<3)
+#define PM2F_CONFIG_FB_PACKED_DATA (1<<2)
+#define PM2F_CONFIG_FB_READ_DEST_ENABLE (1<<1)
+#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE (1<<0)
+#define PM2F_COLOR_KEY_TEST_OFF (1<<4)
+
+#endif /* PM2FB_H */
+
+/*****************************************************************************
+ * That's all folks!
+ *****************************************************************************/
diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c
index 8bfffe147..995e86506 100644
--- a/drivers/video/retz3fb.c
+++ b/drivers/video/retz3fb.c
@@ -178,7 +178,11 @@ static struct fb_videomode retz3fb_predefined[] __initdata = {
"640x480", { /* 640x480, 8 bpp */
640, 480, 640, 480, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+#if 1
+ 0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2,
+#else
0, 0, -1, -1, FB_ACCELF_TEXT, 38461, 28, 32, 12, 10, 96, 2,
+#endif
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
}
},
@@ -194,8 +198,24 @@ static struct fb_videomode retz3fb_predefined[] __initdata = {
FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
}
},
+ {
+ "800x600-60", { /* 800x600, 8 bpp */
+ 800, 600, 800, 600, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
+ FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
+ },
+ {
+ "800x600-70", { /* 800x600, 8 bpp */
+ 800, 600, 800, 600, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCELF_TEXT, 22272, 40, 24, 15, 9, 144, 12,
+ FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
+ },
/*
- ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
+ ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
< name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL
*/
{
@@ -205,14 +225,24 @@ static struct fb_videomode retz3fb_predefined[] __initdata = {
0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 40, 40, 32, 9, 160, 8,
FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
}
- }, {
+ },
+ {
+ "1024x768", {
+ 1024, 768, 1024, 768, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+ }
+ },
+ {
"640x480-16", { /* 640x480, 16 bpp */
640, 480, 640, 480, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 38461/2, 28, 32, 12, 10, 96, 2,
FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
}
- }, {
+ },
+ {
"640x480-24", { /* 640x480, 24 bpp */
640, 480, 640, 480, 0, 0, 24, 0,
{8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
@@ -421,7 +451,7 @@ static int retz3_set_video(struct fb_info *info,
data.h_total = (hback / 8) + (xres / 8)
+ (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
data.h_dispend = ((xres + bpp - 1)/ 8) - 1;
- data.h_bstart = xres / 8 /* + 1 */;
+ data.h_bstart = xres / 8 - 1 /* + 1 */;
data.h_bstop = data.h_total+1 + 2 + 1;
data.h_sstart = (xres / 8) + (hfront / 8) + 1;
@@ -430,7 +460,7 @@ static int retz3_set_video(struct fb_info *info,
data.v_total = yres + vfront + vsync + vback - 1;
data.v_dispend = yres - 1;
- data.v_bstart = yres;
+ data.v_bstart = yres - 1;
data.v_bstop = data.v_total;
data.v_sstart = yres + vfront - 1 - 2;
@@ -727,7 +757,7 @@ static int retz3_set_video(struct fb_info *info,
reg_w(regs, VDAC_MASK, 0xff);
/*
- * Extended palette adressing ???
+ * Extended palette addressing ???
*/
switch (bpp){
case 8:
@@ -1198,7 +1228,7 @@ static void retz3fb_set_disp(int con, struct fb_info *info)
case 8:
if (display->var.accel_flags & FB_ACCELF_TEXT) {
display->dispsw = &fbcon_retz3_8;
-#warning FIXME: We should reinit the graphics engine here
+ retz3_set_video(info, &display->var, &zinfo->current_par);
} else
display->dispsw = &fbcon_cfb8;
break;
@@ -1266,7 +1296,6 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
case 8:
if (var->accel_flags & FB_ACCELF_TEXT) {
display->dispsw = &fbcon_retz3_8;
-#warning FIXME: We should reinit the graphics engine here
} else
display->dispsw = &fbcon_cfb8;
break;
@@ -1280,9 +1309,14 @@ static int retz3fb_set_var(struct fb_var_screeninfo *var, int con,
display->dispsw = &fbcon_dummy;
break;
}
-/*
- retz3fb_set_disp(con, info);
-*/
+ /*
+ * We still need to find a way to tell the X
+ * server that the video mem has been fiddled with
+ * so it redraws the entire screen when switching
+ * between X and a text console.
+ */
+ retz3_set_video(info, var, &zinfo->current_par);
+
if (info->changevar)
(*info->changevar)(con);
}
@@ -1421,8 +1455,7 @@ __initfunc(void retz3fb_init(void))
board_addr = (unsigned long)cd->cd_BoardAddr;
board_size = (unsigned long)cd->cd_BoardSize;
- zinfo->base = kernel_map (board_addr, board_size,
- KERNELMAP_NOCACHE_SER, NULL);
+ zinfo->base = ioremap(board_addr, board_size);
zinfo->regs = (unsigned char *)(zinfo->base);
zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
/* Get memory size - for now we asume its a 4MB board */
diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c
index f4fbe2ec5..88ecf5743 100644
--- a/drivers/video/sbusfb.c
+++ b/drivers/video/sbusfb.c
@@ -46,6 +46,9 @@
#define DEFAULT_CURSOR_BLINK_RATE (2*HZ/5)
+#define CURSOR_SHAPE 1
+#define CURSOR_BLINK 2
+
/*
* Interface used by the world
*/
@@ -457,7 +460,7 @@ sbusfb_cursor_timer_handler(unsigned long dev_addr)
if (!fb->setcursor) return;
- if (fb->cursor.mode != 2) {
+ if (fb->cursor.mode & CURSOR_BLINK) {
fb->cursor.enable ^= 1;
fb->setcursor(fb);
}
@@ -472,14 +475,14 @@ static void sbusfb_cursor(struct display *p, int mode, int x, int y)
switch (mode) {
case CM_ERASE:
- fb->cursor.mode = 2;
+ fb->cursor.mode &= ~CURSOR_BLINK;
fb->cursor.enable = 0;
(*fb->setcursor)(fb);
break;
case CM_MOVE:
case CM_DRAW:
- if (fb->cursor.mode) {
+ if (fb->cursor.mode & CURSOR_SHAPE) {
fb->cursor.size.fbx = fontwidth(p);
fb->cursor.size.fby = fontheight(p);
fb->cursor.chot.fbx = 0;
@@ -492,8 +495,8 @@ static void sbusfb_cursor(struct display *p, int mode, int x, int y)
fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
(*fb->setcurshape) (fb);
- fb->cursor.mode = 0;
}
+ fb->cursor.mode = CURSOR_BLINK;
if (fontwidthlog(p))
fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
else
@@ -684,7 +687,7 @@ static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
lastconsole = info->display_fg->vc_num;
if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
return -EINVAL; /* Don't let graphics programs hide our nice text cursor */
- fb->cursor.mode = 2; /* Forget state of our text cursor */
+ fb->cursor.mode = CURSOR_SHAPE; /* Forget state of our text cursor */
}
return sbus_hw_scursor ((struct fbcursor *) arg, fb);
@@ -761,7 +764,7 @@ static int sbusfbcon_switch(int con, struct fb_info *info)
if (lastconsole != con &&
(fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
- fb->cursor.mode = 1;
+ fb->cursor.mode |= CURSOR_SHAPE;
}
x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
@@ -889,7 +892,7 @@ static int sbusfb_set_font(struct display *p, int width, int height)
p->var.xres = w - 2*x_margin;
p->var.yres = h - 2*y_margin;
- fb->cursor.mode = 1;
+ fb->cursor.mode |= CURSOR_SHAPE;
if (fb->margins)
fb->margins(fb, p, x_margin, y_margin);
@@ -1076,6 +1079,7 @@ sizechange:
add_timer(&fb->cursor.timer);
}
}
+ fb->cursor.mode = CURSOR_SHAPE;
fb->dispsw.set_font = sbusfb_set_font;
fb->setup = fb->dispsw.setup;
fb->dispsw.setup = sbusfb_disp_setup;
@@ -1134,9 +1138,11 @@ __initfunc(void sbusfb_init(void))
int root, node;
root = prom_getchild(prom_root_node);
for (node = prom_searchsiblings(root, "SUNW,ffb"); node;
- node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
+ node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
+ sbusfb_init_fb(node, prom_root_node, FBTYPE_CREATOR, NULL);
+ for (node = prom_searchsiblings(root, "SUNW,afb"); node;
+ node = prom_searchsiblings(prom_getsibling(node), "SUNW,afb"))
sbusfb_init_fb(node, prom_root_node, FBTYPE_CREATOR, NULL);
- }
}
#endif
#ifdef CONFIG_SUN4
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 201984959..fe3bc4068 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -19,6 +19,10 @@
*
* - Hardware cursor (useful for other graphics boards too)
*
+ * - Support for more resolutions
+ *
+ * - Some redraws can stall kernel for several seconds
+ *
* KNOWN PROBLEMS/TO DO ==================================================== */
#include <linux/module.h>
@@ -800,18 +804,56 @@ static int tgafbcon_updatevar(int con, struct fb_info *info)
}
/*
- * Blank the display.
+ * Blank and unblank the display.
*/
static void tgafbcon_blank(int blank, struct fb_info *info)
{
- /* Should also do stuff here for vesa blanking -tor */
+ static int tga_vesa_blanked = 0;
+ u32 vhcr, vvcr;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ vhcr = TGA_READ_REG(TGA_HORIZ_REG);
+ vvcr = TGA_READ_REG(TGA_VERT_REG);
+
+ switch (blank) {
+ case 0: /* Unblanking */
+ if (tga_vesa_blanked) {
+ TGA_WRITE_REG(vhcr & 0xbfffffff, TGA_HORIZ_REG);
+ TGA_WRITE_REG(vvcr & 0xbfffffff, TGA_VERT_REG);
+ tga_vesa_blanked = 0;
+ }
+ TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+ break;
- if (blank > 0) {
+ case 1: /* Normal blanking */
TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
- } else {
- TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+ break;
+
+ case 2: /* VESA blank (vsync off) */
+ TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
+ TGA_WRITE_REG(0x02, TGA_VALID_REG); /* BLANK */
+ tga_vesa_blanked = 1;
+ break;
+
+ case 3: /* VESA blank (hsync off) */
+ TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
+ TGA_WRITE_REG(0x02, TGA_VALID_REG); /* BLANK */
+ tga_vesa_blanked = 1;
+ break;
+
+ case 4: /* Poweroff */
+ TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
+ TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
+ TGA_WRITE_REG(0x02, TGA_VALID_REG); /* BLANK */
+ tga_vesa_blanked = 1;
+ break;
}
+
+ restore_flags(flags);
}
/*
diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c
index 59d16e90b..ba4bf5ea0 100644
--- a/drivers/video/virgefb.c
+++ b/drivers/video/virgefb.c
@@ -32,6 +32,7 @@
#include <asm/irq.h>
#include <asm/pgtable.h>
#include <asm/amigahw.h>
+#include <asm/io.h>
#include <video/s3blit.h>
#include <video/fbcon.h>
@@ -49,7 +50,15 @@
#if 1
#define vgawb_3d(reg,dat) \
- (*((unsigned char *)(CyberVGARegs + (reg ^ 3))) = dat)
+ if (cv3d_on_zorro2) { \
+ *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x04)) = \
+ (0x01 & 0xffff); asm volatile ("nop"); \
+ } \
+ (*((unsigned char *)(CyberVGARegs + (reg ^ 3))) = dat); \
+ if (cv3d_on_zorro2) { \
+ *((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x04)) = \
+ (0x02 & 0xffff); asm volatile ("nop"); \
+ }
#define vgaww_3d(reg,dat) \
(*((unsigned word *)(CyberVGARegs + (reg ^ 2))) = swab16(dat))
#define vgawl_3d(reg,dat) \
@@ -154,6 +163,9 @@ static volatile char *CyberRegs;
static volatile unsigned long CyberVGARegs; /* ++Andre: for CV64/3D, see macros at the beginning */
static unsigned long CyberMem_phys;
static unsigned long CyberRegs_phys;
+static unsigned long Cyber_register_base;
+static unsigned long Cyber_vcode_switch_base;
+static unsigned char cv3d_on_zorro2;
/*
@@ -344,7 +356,11 @@ static int Cyber_init(void)
memset ((char*)CyberMem, 0, 1600 * 1200);
/* Disable hardware cursor */
- CyberSize = 0x00400000; /* 4 MB */
+ if (cv3d_on_zorro2) {
+ CyberSize = 0x00380000; /* 3.5 MB , we need some space for the registers? */
+ } else {
+ CyberSize = 0x00400000; /* 4 MB */
+ }
vgawb_3d(0x3c8, 255);
vgawb_3d(0x3c9, 56);
@@ -1044,21 +1060,26 @@ __initfunc(void virgefb_init(void))
CyberMem_phys = board_addr;
CyberMem = ZTWO_VADDR(CyberMem_phys);
- printk("CV3D detected running in Z2 mode ... not yet supported!\n");
- return;
+ CyberVGARegs = (unsigned long) \
+ ZTWO_VADDR(board_addr + 0x003c0000);
+ CyberRegs_phys = (unsigned long)(board_addr + 0x003e0000);
+ CyberRegs = (unsigned char *)ZTWO_VADDR(CyberRegs_phys);
+ Cyber_register_base = (unsigned long) \
+ ZTWO_VADDR(board_addr + 0x003c8000);
+ Cyber_vcode_switch_base = (unsigned long) \
+ ZTWO_VADDR(board_addr + 0x003a0000);
+ cv3d_on_zorro2 = 1;
+ printk("CV3D detected running in Z2 mode.\n");
}
else
{
- CyberVGARegs = kernel_map(board_addr +0x0c000000, 0x00010000,
- KERNELMAP_NOCACHE_SER, NULL);
+ CyberVGARegs = ioremap(board_addr +0x0c000000, 0x00010000);
CyberRegs_phys = board_addr + 0x05000000;
CyberMem_phys = board_addr + 0x04800000;
- CyberRegs = (char *)kernel_map(CyberRegs_phys,
- 0x00010000,
- KERNELMAP_NOCACHE_SER, NULL);
- CyberMem = kernel_map(CyberMem_phys, 0x00400000,
- KERNELMAP_NOCACHE_SER, NULL);
+ CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
+ CyberMem = ioremap(CyberMem_phys, 0x00400000);
+ cv3d_on_zorro2 = 0;
printk("CV3D detected running in Z3 mode\n");
}
@@ -1083,8 +1104,10 @@ __initfunc(void virgefb_init(void))
virgefb_set_disp(-1, &fb_info);
do_install_cmap(0, &fb_info);
- if (register_framebuffer(&fb_info) < 0)
+ if (register_framebuffer(&fb_info) < 0) {
+ printk("virgefb.c: register_framebuffer failed\n");
return;
+ }
printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);