cronyx.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,061 行 · 第 1/2 页
C
1,061 行
/* * Low-level subroutines for Cronyx-Sigma adapter. * * Copyright (C) 1994-95 Cronyx Ltd. * Author: Serge Vakulenko, <vak@cronyx.ru> * * This software is distributed with NO WARRANTIES, not even the implied * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * Authors grant any other persons or organisations permission to use * or modify this software as long as this message is kept with the software, * all derivative works or modified versions. * * Version 1.6, Wed May 31 16:03:20 MSD 1995 */#if defined (MSDOS) || defined (__MSDOS__)# include <string.h># include <dos.h># define inb(port) inportb(port)# define inw(port) inport(port)# define outb(port,b) outportb(port,b)# define outw(port,w) outport(port,w)# define vtophys(a) (((unsigned long)(a)>>12 & 0xffff0) +\ ((unsigned)(a) & 0xffff))# include "cronyx.h"# include "cxreg.h"#else# include <sys/param.h># include <sys/systm.h># include <sys/socket.h># include <net/if.h># include <vm/vm.h># ifndef __FreeBSD__# include <machine/inline.h># endif# include <machine/cronyx.h># include <i386/isa/cxreg.h>#endif#define DMA_MASK 0xd4 /* DMA mask register */#define DMA_MASK_CLEAR 0x04 /* DMA clear mask */#define DMA_MODE 0xd6 /* DMA mode register */#define DMA_MODE_MASTER 0xc0 /* DMA master mode */#define BYTE *(unsigned char*)&static unsigned char irqmask [] = { BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_3, BCR0_IRQ_DIS, BCR0_IRQ_5, BCR0_IRQ_DIS, BCR0_IRQ_7, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_10, BCR0_IRQ_11, BCR0_IRQ_12, BCR0_IRQ_DIS, BCR0_IRQ_DIS, BCR0_IRQ_15,};static unsigned char dmamask [] = { BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_DIS, BCR0_DMA_5, BCR0_DMA_6, BCR0_DMA_7,};long cx_rxbaud = CX_SPEED_DFLT; /* receiver baud rate */long cx_txbaud = CX_SPEED_DFLT; /* transmitter baud rate */int cx_univ_mode = M_ASYNC; /* univ. chan. mode: async or sync */int cx_sync_mode = M_HDLC; /* sync. chan. mode: HDLC, Bisync or X.21 */int cx_iftype = 0; /* univ. chan. interface: upper/lower */static int cx_probe_chip (int base);static void cx_setup_chip (cx_chip_t *c);/* * Wait for CCR to clear. */void cx_cmd (int base, int cmd){ unsigned short port = CCR(base); unsigned short count; /* Wait 10 msec for the previous command to complete. */ for (count=0; inb(port) && count<20000; ++count) continue; /* Issue the command. */ outb (port, cmd); /* Wait 10 msec for the command to complete. */ for (count=0; inb(port) && count<20000; ++count) continue;}/* * Reset the chip. */static int cx_reset (unsigned short port){ int count; /* Wait up to 10 msec for revision code to appear after reset. */ for (count=0; count<20000; ++count) if (inb(GFRCR(port)) != 0) break; cx_cmd (port, CCR_RSTALL); /* Firmware revision code should clear imediately. */ /* Wait up to 10 msec for revision code to appear again. */ for (count=0; count<20000; ++count) if (inb(GFRCR(port)) != 0) return (1); /* Reset failed. */ return (0);}/* * Check if the CD2400 board is present at the given base port. */static int cx_probe_chained_board (int port, int *c0, int *c1){ int rev, i; /* Read and check the board revision code. */ rev = inb (BSR(port)); *c0 = *c1 = 0; switch (rev & BSR_VAR_MASK) { case CRONYX_100: *c0 = 1; break; case CRONYX_400: *c1 = 1; break; case CRONYX_500: *c0 = *c1 = 1; break; case CRONYX_410: *c0 = 1; break; case CRONYX_810: *c0 = *c1 = 1; break; case CRONYX_410s: *c0 = 1; break; case CRONYX_810s: *c0 = *c1 = 1; break; case CRONYX_440: *c0 = 1; break; case CRONYX_840: *c0 = *c1 = 1; break; case CRONYX_401: *c0 = 1; break; case CRONYX_801: *c0 = *c1 = 1; break; case CRONYX_401s: *c0 = 1; break; case CRONYX_801s: *c0 = *c1 = 1; break; case CRONYX_404: *c0 = 1; break; case CRONYX_703: *c0 = *c1 = 1; break; default: return (0); /* invalid variant code */ } switch (rev & BSR_OSC_MASK) { case BSR_OSC_20: /* 20 MHz */ case BSR_OSC_18432: /* 18.432 MHz */ break; default: return (0); /* oscillator frequency does not match */ } for (i=2; i<0x10; i+=2) if ((inb (BSR(port)+i) & BSR_REV_MASK) != (rev & BSR_REV_MASK)) return (0); /* status changed? */ return (1);}/* * Check if the CD2400 board is present at the given base port. */int cx_probe_board (int port){ int c0, c1, c2=0, c3=0, result; if (! cx_probe_chained_board (port, &c0, &c1)) return (0); /* no board detected */ if (! (inb (BSR(port)) & BSR_NOCHAIN)) { /* chained board attached */ if (! cx_probe_chained_board (port + 0x10, &c2, &c3)) return (0); /* invalid chained board? */ if (! (inb (BSR(port+0x10)) & BSR_NOCHAIN)) return (0); /* invalid chained board flag? */ } /* Turn off the reset bit. */ outb (BCR0(port), BCR0_NORESET); if (c2 || c3) outb (BCR0(port + 0x10), BCR0_NORESET); result = 1; if (c0 && ! cx_probe_chip (CS0(port))) result = 0; /* no CD2400 chip here */ else if (c1 && ! cx_probe_chip (CS1(port))) result = 0; /* no second CD2400 chip */ else if (c2 && ! cx_probe_chip (CS0(port + 0x10))) result = 0; /* no CD2400 chip on the slave board */ else if (c3 && ! cx_probe_chip (CS1(port + 0x10))) result = 0; /* no second CD2400 chip on the slave board */ /* Reset the controller. */ outb (BCR0(port), 0); if (c2 || c3) outb (BCR0(port + 0x10), 0); /* Yes, we really have valid CD2400 board. */ return (result);}/* * Check if the CD2400 chip is present at the given base port. */static int cx_probe_chip (int base){ int rev, newrev, count; /* Wait up to 10 msec for revision code to appear after reset. */ for (count=0; inb(GFRCR(base))==0; ++count) if (count >= 20000) return (0); /* reset failed */ /* Read and check the global firmware revision code. */ rev = inb (GFRCR(base)); if (rev<REVCL_MIN || rev>REVCL_MAX) return (0); /* CD2400 revision does not match */ /* Reset the chip. */ if (! cx_reset (base)) return (0); /* Read and check the new global firmware revision code. */ newrev = inb (GFRCR(base)); if (newrev != rev) return (0); /* revision changed */ /* Yes, we really have CD2400 chip here. */ return (1);}/* * Probe and initialize the board structure. */void cx_init (cx_board_t *b, int num, int port, int irq, int dma){ int rev, chain, rev2; rev = inb (BSR(port)); chain = !(rev & BSR_NOCHAIN); rev2 = chain ? inb (BSR(port+0x10)) : 0; cx_init_board (b, num, port, irq, dma, chain, (rev & BSR_VAR_MASK), (rev & BSR_OSC_MASK), (rev2 & BSR_VAR_MASK), (rev2 & BSR_OSC_MASK));}/* * Initialize the board structure, given the type of the board. */void cx_init_board (cx_board_t *b, int num, int port, int irq, int dma, int chain, int rev, int osc, int rev2, int osc2){ cx_chan_t *c; int i, c0, c1; /* Initialize board structure. */ b->port = port; b->num = num; b->irq = irq; b->dma = dma; b->if0type = b->if8type = cx_iftype; /* Set channels 0 and 8 mode, set DMA and IRQ. */ b->bcr0 = b->bcr0b = BCR0_NORESET | dmamask[b->dma] | irqmask[b->irq]; /* Clear DTR[0..3] and DTR[8..12]. */ b->bcr1 = b->bcr1b = 0; /* Initialize chip structures. */ for (i=0; i<NCHIP; ++i) { b->chip[i].num = i; b->chip[i].board = b; } b->chip[0].port = CS0(port); b->chip[1].port = CS1(port); b->chip[2].port = CS0(port+0x10); b->chip[3].port = CS1(port+0x10); /*------------------ Master board -------------------*/ /* Read and check the board revision code. */ c0 = c1 = 0; b->name[0] = 0; switch (rev) { case CRONYX_100: strcpy (b->name, "100"); c0 = 1; break; case CRONYX_400: strcpy (b->name, "400"); c1 = 1; break; case CRONYX_500: strcpy (b->name, "500"); c0 = c1 = 1; break; case CRONYX_410: strcpy (b->name, "410"); c0 = 1; break; case CRONYX_810: strcpy (b->name, "810"); c0 = c1 = 1; break; case CRONYX_410s: strcpy (b->name, "410s"); c0 = 1; break; case CRONYX_810s: strcpy (b->name, "810s"); c0 = c1 = 1; break; case CRONYX_440: strcpy (b->name, "440"); c0 = 1; break; case CRONYX_840: strcpy (b->name, "840"); c0 = c1 = 1; break; case CRONYX_401: strcpy (b->name, "401"); c0 = 1; break; case CRONYX_801: strcpy (b->name, "801"); c0 = c1 = 1; break; case CRONYX_401s: strcpy (b->name, "401s"); c0 = 1; break; case CRONYX_801s: strcpy (b->name, "801s"); c0 = c1 = 1; break; case CRONYX_404: strcpy (b->name, "404"); c0 = 1; break; case CRONYX_703: strcpy (b->name, "703"); c0 = c1 = 1; break; } switch (osc) { default: case BSR_OSC_20: /* 20 MHz */ b->chip[0].oscfreq = b->chip[1].oscfreq = 20000000L; strcat (b->name, "a"); break; case BSR_OSC_18432: /* 18.432 MHz */ b->chip[0].oscfreq = b->chip[1].oscfreq = 18432000L; strcat (b->name, "b"); break; } if (! c0) b->chip[0].port = 0; if (! c1) b->chip[1].port = 0; /*------------------ Slave board -------------------*/ if (! chain) { b->chip[2].oscfreq = b->chip[3].oscfreq = 0L; b->chip[2].port = b->chip[3].port = 0; } else { /* Read and check the board revision code. */ c0 = c1 = 0; strcat (b->name, "/"); switch (rev2) { case CRONYX_100: strcat(b->name,"100"); c0=1; break; case CRONYX_400: strcat(b->name,"400"); c1=1; break; case CRONYX_500: strcat(b->name,"500"); c0=c1=1; break; case CRONYX_410: strcat(b->name,"410"); c0=1; break; case CRONYX_810: strcat(b->name,"810"); c0=c1=1; break; case CRONYX_410s: strcat(b->name,"410s"); c0=1; break; case CRONYX_810s: strcat(b->name,"810s"); c0=c1=1; break; case CRONYX_440: strcat(b->name,"440"); c0=1; break; case CRONYX_840: strcat(b->name,"840"); c0=c1=1; break; case CRONYX_401: strcat(b->name,"401"); c0=1; break; case CRONYX_801: strcat(b->name,"801"); c0=c1=1; break; case CRONYX_401s: strcat(b->name,"401s"); c0=1; break; case CRONYX_801s: strcat(b->name,"801s"); c0=c1=1; break; case CRONYX_404: strcat(b->name,"404"); c0=1; break; case CRONYX_703: strcat(b->name,"703"); c0=c1=1; break; } switch (osc2) { default: case BSR_OSC_20: /* 20 MHz */ b->chip[2].oscfreq = b->chip[3].oscfreq = 20000000L; strcat (b->name, "a"); break; case BSR_OSC_18432: /* 18.432 MHz */ b->chip[2].oscfreq = b->chip[3].oscfreq = 18432000L; strcat (b->name, "b"); break; } if (! c0) b->chip[2].port = 0; if (! c1) b->chip[3].port = 0; } /* Initialize channel structures. */ for (i=0; i<NCHAN; ++i) { cx_chan_t *c = b->chan + i; c->num = i; c->board = b; c->chip = b->chip + i*NCHIP/NCHAN; c->stat = b->stat + i; c->type = T_NONE; } /*------------------ Master board -------------------*/ switch (rev) { case CRONYX_400: break; case CRONYX_100: case CRONYX_500: b->chan[0].type = T_UNIV_RS232; break; case CRONYX_410: case CRONYX_810: b->chan[0].type = T_UNIV_V35; for (i=1; i<4; ++i) b->chan[i].type = T_UNIV_RS232; break; case CRONYX_410s: case CRONYX_810s: b->chan[0].type = T_UNIV_V35; for (i=1; i<4; ++i) b->chan[i].type = T_SYNC_RS232; break; case CRONYX_440: case CRONYX_840: b->chan[0].type = T_UNIV_V35; for (i=1; i<4; ++i) b->chan[i].type = T_SYNC_V35; break; case CRONYX_401: case CRONYX_801: b->chan[0].type = T_UNIV_RS449; for (i=1; i<4; ++i) b->chan[i].type = T_UNIV_RS232; break; case CRONYX_401s: case CRONYX_801s: b->chan[0].type = T_UNIV_RS449; for (i=1; i<4; ++i) b->chan[i].type = T_SYNC_RS232; break; case CRONYX_404: b->chan[0].type = T_UNIV_RS449; for (i=1; i<4; ++i) b->chan[i].type = T_SYNC_RS449; break; case CRONYX_703: b->chan[0].type = T_UNIV_RS449; for (i=1; i<3; ++i) b->chan[i].type = T_SYNC_RS449; break; } /* If the second controller is present, * then we have 4..7 channels in async. mode */ if (b->chip[1].port) for (i=4; i<8; ++i) b->chan[i].type = T_UNIV_RS232; /*------------------ Slave board -------------------*/ if (chain) { switch (rev2) { case CRONYX_400: break; case CRONYX_100: case CRONYX_500: b->chan[8].type = T_UNIV_RS232; break; case CRONYX_410: case CRONYX_810: b->chan[8].type = T_UNIV_V35; for (i=9; i<12; ++i) b->chan[i].type = T_UNIV_RS232; break; case CRONYX_410s: case CRONYX_810s: b->chan[8].type = T_UNIV_V35; for (i=9; i<12; ++i) b->chan[i].type = T_SYNC_RS232; break; case CRONYX_440: case CRONYX_840: b->chan[8].type = T_UNIV_V35; for (i=9; i<12; ++i) b->chan[i].type = T_SYNC_V35; break; case CRONYX_401: case CRONYX_801: b->chan[8].type = T_UNIV_RS449; for (i=9; i<12; ++i) b->chan[i].type = T_UNIV_RS232; break; case CRONYX_401s: case CRONYX_801s: b->chan[8].type = T_UNIV_RS449; for (i=9; i<12; ++i) b->chan[i].type = T_UNIV_RS232; break; case CRONYX_404: b->chan[8].type = T_UNIV_RS449; for (i=9; i<12; ++i) b->chan[i].type = T_SYNC_RS449; break; case CRONYX_703: b->chan[8].type = T_UNIV_RS449; for (i=9; i<11; ++i) b->chan[i].type = T_SYNC_RS449; break; } /* If the second controller is present, * then we have 4..7 channels in async. mode */ if (b->chip[3].port) for (i=12; i<16; ++i) b->chan[i].type = T_UNIV_RS232; } b->nuniv = b->nsync = b->nasync = 0; for (c=b->chan; c<b->chan+NCHAN; ++c) switch (c->type) { case T_ASYNC: ++b->nasync; break; case T_UNIV_RS232: case T_UNIV_RS449: case T_UNIV_V35: ++b->nuniv; break; case T_SYNC_RS232: case T_SYNC_V35: case T_SYNC_RS449: ++b->nsync; break; } cx_reinit_board (b);}/* * Reinitialize all channels, using new options and baud rate. */void cx_reinit_board (cx_board_t *b){ cx_chan_t *c; b->if0type = b->if8type = cx_iftype; for (c=b->chan; c<b->chan+NCHAN; ++c) { switch (c->type) { default: case T_NONE: continue; case T_UNIV_RS232: case T_UNIV_RS449: case T_UNIV_V35: c->mode = (cx_univ_mode == M_ASYNC) ? M_ASYNC : cx_sync_mode; break; case T_SYNC_RS232: case T_SYNC_V35: case T_SYNC_RS449: c->mode = cx_sync_mode; break; case T_ASYNC: c->mode = M_ASYNC; break; } c->rxbaud = cx_rxbaud; c->txbaud = cx_txbaud;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?