home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / bmd-1.0beta.tar.Z / bmd-1.0beta.tar / bmd-1.0beta / sundev / zs_midi.c < prev    next >
C/C++ Source or Header  |  1991-08-27  |  9KB  |  452 lines

  1. /*
  2.  * Copyright (c) 1990 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Lawrence Berkeley Laboratory,
  11.  * Berkeley, CA.  The name of the University may not be used to
  12.  * endorse or promote products derived from this software without
  13.  * specific prior written permission.
  14.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17.  *
  18.  * Low level (one mdq at a time) tap to 8530 UART.
  19.  * Works by stealing the chip away from the zs async driver.  
  20.  * Too bad zsopinit() doesn't do proper resource bookeeping,
  21.  * otherwise things would work correctly.
  22.  */
  23.  
  24. #include "bmd.h"
  25.  
  26. #if NBMD > 0
  27. #ifndef lint
  28. static char rcsid[] =
  29.     "@(#) $Header: zs_midi.c,v 1.11 91/08/27 00:37:20 mccanne Exp $";
  30. #endif
  31.  
  32. #include <sys/systm.h>
  33. #include <sys/param.h>
  34.  
  35. /*
  36.  * Sun mixed software-only data structures with hardware register
  37.  * definitions in zsreg.h.  This was a very bad idea.  Instead of
  38.  * including a bunch of streams crap for struct zsaline in zsreg.h,
  39.  * we define away the offending type names.  (None of the code below
  40.  * references a zsaline).
  41.  */
  42. #define mblk_t void*
  43. #define tty_common_t void*
  44. #include <sundev/zsreg.h>
  45. #include <sundev/zscom.h>
  46.  
  47. #include <sundev/midi.h>
  48. #include <sundev/bmdvar.h>
  49. #include <sundev/zs_midi.h>
  50.  
  51. static int zsmidi_txint();
  52. static int zsmidi_xsint();
  53. static int zsmidi_rxint();
  54. static int zsmidi_srint();
  55.  
  56. static int
  57. zsmidi_null()
  58. {
  59.     return 0;
  60. }
  61.  
  62. struct zsops zsops_hook = {
  63.     zsmidi_null,
  64.     zsmidi_txint,
  65.     zsmidi_xsint,
  66.     zsmidi_rxint,
  67.     zsmidi_srint,
  68.     zsmidi_null,
  69. };
  70.  
  71. #define ZMFC_NONE    0
  72. #define ZMFC_SW        1
  73. #define ZMFC_HW        2
  74.  
  75. #ifndef MIDIRATE
  76. #define MIDIRATE 31250
  77. #endif
  78.  
  79. #if MIDIRATE == 31250
  80. int zsmidi_fc = ZMFC_NONE;
  81. #else
  82. int zsmidi_fc = ZMFC_HW;
  83. #endif
  84.  
  85. struct zsmidi {
  86.     struct zscom *zm_common;    /* address of zs common data struct */
  87.     caddr_t zm_private;        /* midi softc pointer */
  88.  
  89.     struct mdq *zm_qh;        /* output queue head */
  90.     struct mdq *zm_qt;        /* output queue tail */
  91.  
  92.     int zm_speed;
  93.     u_char zm_busy;
  94.     u_char zm_status;
  95.     u_char zm_sleep;
  96.     u_char zm_fc;
  97.     /*
  98.      * Various stats, mainly for debugging.
  99.      */
  100.     int zm_pe;
  101.     int zm_overrun;
  102.     int zm_txdrops;
  103.  
  104. };
  105.  
  106. #define NPORTS 2
  107. struct zsmidi zsmidi[NPORTS];
  108.  
  109. void
  110. msl_disconnect(arg, drain)
  111.     void *arg;
  112.     int drain;
  113. {
  114.     struct zsmidi *zm = (struct zsmidi *)arg;
  115.     register struct zscom *zs = zm->zm_common;
  116.  
  117.     if (zm->zm_qh != 0) {
  118.         if (drain) {
  119.             zm->zm_sleep = 1;
  120.             (void)sleep((caddr_t)zm, (PZERO+1)|PCATCH);
  121.             zm->zm_sleep = 0;
  122.         }
  123.         mdqfreeq(zm->zm_qh, zm->zm_qt);
  124.         zm->zm_qt = zm->zm_qh = 0;
  125.     }
  126.     ZBIC(1, ZSWR1_RIE);
  127. }
  128.  
  129. #include <machine/param.h>
  130. #ifdef OPENPROMS
  131. extern struct zscom *zscom;
  132. #else
  133. extern struct zscom zscom[];
  134. #endif
  135.  
  136. extern int hz;
  137.  
  138. static void
  139. msl_watchdog(arg)
  140.     caddr_t arg;
  141. {
  142.     ((struct zsmidi *)arg)->zm_status = 0;
  143.     timeout((int (*)())msl_watchdog, arg, 3 * hz);
  144. }
  145.  
  146. /*
  147.  * This is probably 31.25kb, but it might be 38400.  
  148.  */
  149. int midi_speed = MIDIRATE;
  150.  
  151. void *
  152. msl_init(unit, private)
  153.     int unit;
  154.     caddr_t private;
  155. {
  156.     int s;
  157.     struct zsmidi *zm = &zsmidi[unit];
  158.     register struct zscom *zs = &zscom[unit];
  159.  
  160.     zm->zm_common = zs;
  161.     zm->zm_private = private;
  162.     zm->zm_qh = 0;
  163.     zm->zm_qt = 0;
  164.     zm->zm_speed = ZSTimeConst(4915200, midi_speed);
  165.     zm->zm_busy = 0;
  166.     zm->zm_status = 0;
  167.     zm->zm_sleep = 0;
  168.     zm->zm_fc = zsmidi_fc;
  169.     zm->zm_pe = 0;
  170.     zm->zm_overrun = 0;
  171.      zm->zm_txdrops = 0;
  172.  
  173.     s = splzs();
  174.     zs->zs_priv = (caddr_t)zm;
  175.     /*
  176.      * This call will grab the chip, even if something else has it.
  177.      */
  178.     zsopinit(zs, &zsops_hook);
  179.     msl_chipinit(zm);
  180.     (void)splx(s);
  181.  
  182.     /*
  183.      * Start up a watch dog to reset the running status every
  184.      * three seconds, so we can move midi cables and power up
  185.      * devices.
  186.      */
  187.     timeout((int (*)())msl_watchdog, (caddr_t)zm, 3 * hz);
  188.  
  189.     return (void *)zm;
  190. }
  191.  
  192. void
  193. msl_setspeed(arg, speed)
  194.     void *arg;
  195.     int speed;
  196. {
  197.     int s;
  198.     struct zsmidi *zm = (struct zsmidi *)arg;
  199.  
  200.     s = splmidi();
  201.     zm->zm_speed = speed;
  202.     msl_chipinit(zm);
  203.     zm->zm_busy = 0;
  204.     splx(s);
  205. }
  206.  
  207. /*
  208.  * Set the chip up for MIDI operation.
  209.  */
  210. msl_chipinit(zm)
  211.     register struct zsmidi *zm;
  212. {
  213.     register struct zscom *zs = zm->zm_common;
  214.     register int x, speed;
  215.     char c;
  216.  
  217.     /* Disable receiver */
  218.     ZWRITE(3, 0);
  219.     zs->zs_addr->zscc_control = ZSWR0_RESET_STATUS;
  220.     ZSDELAY(2);
  221.     zs->zs_addr->zscc_control = ZSWR0_RESET_ERRORS;
  222.     ZSDELAY(2);
  223.  
  224.     /*
  225.      * Drain on-chip FIFO.
  226.      */
  227.     c = zs->zs_addr->zscc_data;
  228.     ZSDELAY(2);
  229.     c = zs->zs_addr->zscc_data;
  230.     ZSDELAY(2);
  231.     c = zs->zs_addr->zscc_data;
  232.     ZSDELAY(2);
  233.  
  234.     /*
  235.      * Set interrupt enable bits.
  236.      */
  237.     x = ZSWR1_RIE|ZSWR1_SIE;
  238.     if (zm->zm_fc != ZMFC_SW)
  239.         x |= ZSWR1_TIE;
  240.     ZWRITE(1, x);
  241.  
  242.     /*
  243.      * 2 stop bits.
  244.      */
  245.     ZWRITE(4, ZSWR4_X16_CLK | ZSWR4_2_STOP);
  246.     /*
  247.      * Enable the receiver; 8 data bits.
  248.      * If transmitter interrupts will be used, hardware flow
  249.      * control *must* be on.
  250.      */
  251.     x = ZSWR3_RX_ENABLE|ZSWR3_RX_8;
  252.     if (zm->zm_fc == ZMFC_HW)
  253.         x |= ZSWR3_AUTO_CD_CTS;
  254.     ZWRITE(3, x);
  255.  
  256.     /*
  257.      * XXX RTS and DTR must remain in opposite state in order for
  258.      * the MIDI interface to extract power from the port.
  259.      */
  260.     ZWRITE(5, ZSWR5_DTR | ZSWR5_RTS | ZSWR5_TX_ENABLE | ZSWR5_TX_8);
  261.  
  262.     ZWRITE(11, ZSWR11_TXCLK_BAUD + ZSWR11_RXCLK_BAUD);
  263.     /*
  264.      * Set the line speed.
  265.      */
  266.     ZWRITE(14, ZSWR14_BAUD_FROM_PCLK);
  267.     speed = zm->zm_speed;
  268.     ZWRITE(12, speed);
  269.     ZWRITE(13, speed >> 8);
  270.     ZWRITE(14, ZSWR14_BAUD_ENA + ZSWR14_BAUD_FROM_PCLK);
  271.     /*
  272.      * If doing software flow control, enable interrupts on 
  273.      * cts transitions.
  274.      */
  275.     if (zm->zm_fc == ZMFC_SW)
  276.         ZWRITE(15, ZSR15_CTS);
  277. }
  278.  
  279. static int
  280. msl_out(zm)
  281.     register struct zsmidi *zm;
  282. {
  283.     register struct mdq *q, *n;
  284.     register int c;
  285.  again:
  286.     q = zm->zm_qh;
  287.     if (q == 0)
  288.         return 0;
  289.  
  290.     c = *q->mq_cp++;
  291.     if (--q->mq_len <= 0) {
  292.         n = q->mq_next;
  293.         if (n == 0)
  294.             zm->zm_qt = 0;
  295.         zm->zm_qh = n;
  296.         mdqfree(q);
  297.     }
  298.     if (c & 0x80) {
  299.         /*
  300.          * This is a status byte.  If the running status
  301.          * won't change, go get another byte.
  302.          */
  303.         if (c == zm->zm_status)
  304.             goto again;
  305.         /*
  306.          * Record the new status.  Real time commands (f8-ff)
  307.          * don't affect the state so ignore them.  If it's a system
  308.          * message (f1-f7) reset the status.
  309.          */
  310.         if (c < 0xf8)
  311.             zm->zm_status = (c < 0xf0) ? c : 0;
  312.     }
  313.     zm->zm_common->zs_addr->zscc_data = c;
  314.     ZSDELAY(2);
  315.     return 1;
  316. }
  317.  
  318. /*
  319.  * Start output on the transmitter if it's ready.
  320.  * Must be called at splmidi.
  321.  */
  322. void
  323. msl_output(arg, head, tail)
  324.     void *arg;
  325.     register struct mdq *head;
  326.     register struct mdq *tail;
  327. {
  328.     register struct zsmidi *zm = (struct zsmidi *)arg;
  329.  
  330.     if (zm->zm_qt == 0) {
  331.         zm->zm_qh = head;
  332.         zm->zm_qt = tail;
  333.     } else {
  334.         zm->zm_qt->mq_next = head;
  335.         zm->zm_qt = tail;
  336.     }
  337.     tail->mq_next = 0;
  338.     if (zm->zm_busy == 0)
  339.         zm->zm_busy = msl_out(zm);
  340. }
  341.  
  342. /*
  343.  * Transmitter interrupt service routine.
  344.  */
  345. static int
  346. zsmidi_txint(zs)
  347.     register struct zscom *zs;
  348. {
  349.     register struct zsmidi *zm = (struct zsmidi *)zs->zs_priv;
  350.     register int s;
  351.  
  352.     s = splmidi();
  353.     zm->zm_busy = msl_out(zm);
  354.     if (!zm->zm_busy && zm->zm_sleep)
  355.         wakeup((caddr_t)zm);
  356.  
  357.     zs->zs_addr->zscc_control = ZSWR0_RESET_TXINT;
  358.     splx(s);
  359. }
  360.  
  361. /*
  362.  * External/Status interrupt.
  363.  *
  364.  */
  365. static int
  366. zsmidi_xsint(zs)
  367.     register struct zscom *zs;
  368. {
  369.     register struct zsmidi *zm = (struct zsmidi *)zs->zs_priv;
  370.     register struct zscc_device *zsaddr = zs->zs_addr;
  371.     register int s;
  372.  
  373.     if (zm->zm_fc != ZMFC_SW) {
  374.         zsaddr->zscc_control = ZSWR0_RESET_STATUS;
  375.         return;
  376.     }
  377.     /*
  378.      * If hardware flow control won't work (because the SLC has no
  379.      * modem control lines on port B), we handle output here.
  380.      * Because of the mismatch in baud rates, we must use flow control.
  381.      * We wait for the other side to say that they're ready (CTS).
  382.      */
  383.     s = zsaddr->zscc_control;
  384.     ZSDELAY(2);
  385.     if (s & ZSRR0_CTS) {
  386.         if ((s & ZSRR0_TX_READY) == 0) {
  387.             /*
  388.              * If we're doing software flow control, but the
  389.              * transmission isn't as fast as the external 
  390.              * device, we lose and shouldn't be using this
  391.              * mode.  Just drop the byte.
  392.              */
  393.             ++zm->zm_txdrops;
  394.         } else {
  395.             s = splmidi();
  396.             zm->zm_busy = msl_out(zm);
  397.             splx(s);
  398.         }
  399.     }
  400.     zsaddr->zscc_control = ZSWR0_RESET_STATUS;
  401. }
  402.  
  403. /*
  404.  * Receiver interrupt.  Pass character up to higher level.
  405.  */
  406. static int
  407. zsmidi_rxint(zs)
  408.     register struct zscom *zs;
  409. {
  410.     register int s = splmidi();
  411.  
  412.     bmdinput(((struct zsmidi *)zs->zs_priv)->zm_private, 
  413.          zs->zs_addr->zscc_data);
  414.     splx(s);
  415. }
  416.  
  417. /*
  418.  * Special receive condition interrupt handler.
  419.  */
  420. static int
  421. zsmidi_srint(zs)
  422.     register struct zscom *zs;
  423. {
  424.     register struct zsmidi *zm = (struct zsmidi *)zs->zs_priv;
  425.     register struct zscc_device *zsaddr = zs->zs_addr;
  426.     register short s1;
  427.     register u_char c;
  428.  
  429.     s1 = ZREAD(1);
  430.     ZSDELAY(2);
  431.     /*
  432.      * Drain bogus character.
  433.      */
  434.     c = zsaddr->zscc_data;
  435.     ZSDELAY(2);
  436.     if (s1 & ZSRR1_PE)
  437.         /*
  438.          * Log parity error.
  439.          */
  440.         ++zm->zm_pe;
  441.  
  442.     zsaddr->zscc_control = ZSWR0_RESET_ERRORS;
  443.     ZSDELAY(2);
  444.     if (s1 & ZSRR1_DO)
  445.         /*
  446.          * Log hardware overrun.
  447.          */
  448.         ++zm->zm_overrun;
  449. }
  450.  
  451. #endif
  452.