/* * y701ini.c - version 1.0, March 1999 * * Init a soundcard with Yamaha Y701 chip (OPL3-SA) * * (c) Ivan Popov 1999 * * Then you may use the card as two independent cards, * namely CS4231-based one (16 bit duplex), * and SoundBlaster-Pro (8 bit non-duplex, input not connected on my card). * * Suitable sound modules are * oss: sb + ad1848 + opl3 * load sb first (if at all), otherwise it may crash the system (why?! :) * alsa: card-cs4231 + sb8 * card-cs4231 module wants different port address * than you tell to y701ini (and oss ad1848 module), * you have to add 4, and it's not a bug: * y701ini wss_io=0x530 ... ad1848 io=0x530 ... * but y701ini wss_io=0x530 ... card-cs4231 snd_port=0x534 ... * ^^^^^ * A hack (this program), but it works well. Reasonably self-documented :) * * Please mention me as the author, * otherwise do what you want with this program. * * For those who do not know (yet) - the language below is Esperanto. */ /* * Tiu cxi programo inicas sonkarton kun Yamaha-701 mikrocirkvito. * * La parametroj estas sekvaj: * * wss-adreso: unu el 0x530,0xe80,0xf40,0x604,- * wss-interrompo: unu el 7,9,10,11 * wss-dma: unu el 0,1,3,0+1,1+0,3+0 * mpu-adreso: unu el 0x330,0x332,0x334,0x300,- * mpu-interrompo: unu el 5,7,9,10 * sb-adreso: unu el 0x220,0x240,- * sb-interrompo: unu el 5,7,9,10,11 * sb-dma: unu el 0,1,3 * * bedauxre pro la abunda uzo de la angla en tiu cxi programo... * * Ivan Popov, marto 1999 */ #define IOFILE "/dev/port" #include #include #include #include #include static int ports; static unsigned int i8( int port ) { char v8 = 0x17; if( lseek(ports, (off_t) port, SEEK_SET) == -1 ){ perror("8-bit port lseek error"); exit( 2 ); } if( read(ports,&v8,1) != 1 ){ perror("8-bit port read error"); exit( 2 ); } return (unsigned int) (unsigned char) v8; } static void o8( int port, int value ) { char v8 = value; if( lseek(ports, (off_t) port, SEEK_SET) == -1 ){ perror("8-bit port lseek error"); exit( 2 ); } if( write(ports,&value,1) != 1 ){ perror("8-bit port write error"); exit( 2 ); } } static void o16( int port, int value ) { char v16[2]; v16[0] = (value & 0xff); v16[1] = ((value >> 8) & 0xff); if( lseek(ports, (off_t) port, SEEK_SET) == -1 ){ perror("16-bit port lseek error"); exit( 2 ); } if( write(ports,&value,2) != 2 ){ perror("16-bit port write error"); exit( 2 ); } } static void mperror( char *s ) { fprintf( stderr, "%s\n", s ); exit( 1 ); } /**************************************/ int opl3sa_read(int addr) { o8( 0xf86, 0x1d ); /* password */ o8( 0xf86, addr ); /* address */ return i8( 0xf87 ); /* data */ } void opl3sa_write(int addr, int value) { o8( 0xf86, 0x1d ); /* password */ o8( 0xf86, addr ); /* address */ o8( 0xf87, value ); /* data */ } /**************************************/ main(int argc, char **argv) { char *p; int wss_value, wss_addr, wss_irq_value, wss_dma_value, mpu_value, mpu_irq_value, sb_value, sb_irq_value, dma_value; int wss_flag, mpu_flag, sb_flag; if( argc != 9 ){ mperror("\ exactly 8 arguments required:\n\ wss_io=xxx wss_irq=xxx wss_dma=xxx\n\ mpu_io=xxx mpu_irq=xxx\n\ sb_io=xxx sb_irq=xxx sb_dma=xxx"); } p = argv[1]; wss_flag = 1; if( !strcmp(p,"wss_io=0x530") ){ wss_value = 0x24; wss_addr=0x530; } else if( !strcmp(p,"wss_io=0xe80") ){ wss_value = (0x24|0x08); wss_addr=0xe80; } else if( !strcmp(p,"wss_io=0xf40") ){ wss_value = (0x24|0x10); wss_addr=0xf40; } else if( !strcmp(p,"wss_io=0x604") ){ wss_value = (0x24|0x18); wss_addr=0x604; } else if( !strcmp(p,"wss_io=-") ){ wss_flag = 0; } else { mperror("wss_io value must be one of 0x530,0xe80,0xf40,0x604,-"); } if( wss_flag ){ p = argv[2]; if( !strcmp(p,"wss_irq=7") ){ wss_irq_value = 0x08; } else if( !strcmp(p,"wss_irq=9") ){ wss_irq_value = 0x10; } else if( !strcmp(p,"wss_irq=10") ){ wss_irq_value = 0x18; } else if( !strcmp(p,"wss_irq=11") ){ wss_irq_value = 0x20; } else { mperror("wss_irq value must be one of 7,9,10,11"); } p = argv[3]; if( !strcmp(p,"wss_dma=0") ){ wss_dma_value = 0x01; } else if( !strcmp(p,"wss_dma=1") ){ wss_dma_value = 0x02; } else if( !strcmp(p,"wss_dma=3") ){ wss_dma_value = 0x03; } else if( !strcmp(p,"wss_dma=0+1") ){ wss_dma_value = 0x05; } else if( !strcmp(p,"wss_dma=1+0") ){ wss_dma_value = 0x06; } else if( !strcmp(p,"wss_dma=3+0") ){ wss_dma_value = 0x07; } else { mperror("wss_dma value must be one of 0,1,3,0+1,1+0,3+0"); } } p = argv[4]; mpu_flag = 1; if( !strcmp(p,"mpu_io=0x330") ){ mpu_value = 0x00; } else if( !strcmp(p,"mpu_io=0x332") ){ mpu_value = 0x20; } else if( !strcmp(p,"mpu_io=0x334") ){ mpu_value = 0x40; } else if( !strcmp(p,"mpu_io=0x300") ){ mpu_value = 0x60; } else if( !strcmp(p,"mpu_io=-") ){ mpu_flag = 0; } else { mperror("mpu_io value must be one of 0x330,0x332,0x334,0x300,-"); } if( mpu_flag ){ p = argv[5]; if( !strcmp(p,"mpu_irq=5") ){ mpu_irq_value = 1; } else if( !strcmp(p,"mpu_irq=7") ){ mpu_irq_value = 2; } else if( !strcmp(p,"mpu_irq=9") ){ mpu_irq_value = 3; } else if( !strcmp(p,"mpu_irq=10") ){ mpu_irq_value = 4; } else { mperror("mpu_irq value must be one of 5,7,9,10"); } } p = argv[6]; sb_flag = 1; if( !strcmp(p,"sb_io=0x220") ){ sb_value = 0x00; } else if( !strcmp(p,"sb_io=0x240") ){ sb_value = 0x20; } else if( !strcmp(p,"sb_io=-") ){ sb_flag = 0; } else { mperror("sb_io value must be one of 0x220,0x240,-"); } if( sb_flag ){ p = argv[7]; if( !strcmp(p,"sb_irq=5") ){ sb_irq_value = 1; } else if( !strcmp(p,"sb_irq=7") ){ sb_irq_value = 2; } else if( !strcmp(p,"sb_irq=9") ){ sb_irq_value = 3; } else if( !strcmp(p,"sb_irq=10") ){ sb_irq_value = 4; } else if( !strcmp(p,"sb_irq=11") ){ sb_irq_value = 5; } else { mperror("sb_irq value must be one of 5,7,9,10,11"); } p = argv[8]; if( !strcmp(p,"sb_dma=0") ){ dma_value = 1; } else if( !strcmp(p,"sb_dma=1") ){ dma_value = 2; } else if( !strcmp(p,"sb_dma=3") ){ dma_value = 3; } else { mperror("sb_dma value must be one of 0,1,3"); } } if( (ports=open(IOFILE,O_RDWR)) == -1 ){ perror(IOFILE); exit( 1 ); } opl3sa_write(0x01, 0x00); /* Disable MSS */ opl3sa_write(0x02, 0x00); /* Disable SB */ opl3sa_write(0x03, 0x00); /* Disable MPU */ if ( wss_flag ){ /* Setup MSS */ opl3sa_write(0x01, wss_value); o8( wss_addr, wss_irq_value|0x40 ); /* Setup irq */ o8( wss_addr, wss_irq_value|wss_dma_value); /* Setup dma */ } if( sb_flag ){ /* Setup SB */ opl3sa_write(0x02, 0x40|sb_value|(sb_irq_value<<2)|dma_value); } if( mpu_flag ){ /* Setup MPU */ mpu_value |= 0x83; /* MPU & OPL3 (synth) & game port enable */ mpu_value |= mpu_irq_value << 2; opl3sa_write(0x03, mpu_value); } return 0; } .