📄 pi2.c
字号:
lp->tstate = ACTIVE; /* char going out now */ restore_flags(flags); return; case DEFER: /* Check DCD - debounce it * See Intel Microcommunications Handbook, p2-308 */ wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT); wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT); if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) { lp->tstate = DEFER; tdelay(lp, 100); /* defer until DCD transition or timeout */ wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE); restore_flags(flags); return; } if (random() > lp->persist) { lp->tstate = DEFER; tdelay(lp, lp->slotime); restore_flags(flags); return; } rts(lp, ON); /* Transmitter on */ lp->tstate = ST_TXDELAY; tdelay(lp, lp->txdelay); restore_flags(flags); return; case ST_TXDELAY: /* Get first char to send */ lp->txcnt--; c = *lp->txptr++; wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC); /* reset for next frame */ /* Send abort on underrun */ if (lp->speed) { /* If internally clocked */ wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER); } else { wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER); } wrtscc(lp->cardbase, cmd, R8, c); /* First char out now */ wrtscc(lp->cardbase, cmd, R0, RES_EOM_L); /* Reset end of message latch */#ifdef STUFF2 /* stuff an extra one if we can */ if (lp->txcnt) { lp->txcnt--; c = *lp->txptr++; /* Wait for tx buffer empty */ while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0) ; wrtscc(lp->cardbase, cmd, R8, c); }#endif /* select transmit interrupts to enable */ wrtscc(lp->cardbase, cmd, R15, TxUIE); /* allow Underrun int only */ wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT); /* Tx/Extern ints on */ wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB); lp->tstate = ACTIVE; /* char going out now */ restore_flags(flags); return; } /* Receive Mode only * This triggers when hunt mode is entered, & since an ABORT * automatically enters hunt mode, we use that to clean up * any waiting garbage */ if ((lp->rstate == ACTIVE) && (st & BRK_ABRT)) { (void) rdscc(lp->cardbase, cmd, R8); (void) rdscc(lp->cardbase, cmd, R8); (void) rdscc(lp->cardbase, cmd, R8); lp->rcp = lp->rcvbuf->data; lp->rcvbuf->cnt = 0; /* rewind on DCD transition */ } restore_flags(flags);}/* Probe for a PI card. *//* This routine also initializes the timer chip */__initfunc(static int hw_probe(int ioaddr)){ int time = 1000; /* Number of milliseconds for test */ unsigned long start_time, end_time; int base, tmr0, tmr1, tmrcmd; int a = 1; int b = 1; base = ioaddr & 0x3f0; tmr0 = TMR0 + base; tmr1 = TMR1 + base; tmrcmd = TMRCMD + base; /* Set up counter chip timer 0 for 500 uS period square wave */ /* assuming a 3.68 mhz clock for now */ outb_p(SC0 | LSB_MSB | MODE3, tmrcmd); outb_p(922 & 0xFF, tmr0); outb_p(922 >> 8, tmr0); /* Setup timer control word for timer 1*/ outb_p(SC1 | LSB_MSB | MODE0, tmrcmd); outb_p((time << 1) & 0xFF, tmr1); outb_p((time >> 7) & 0XFF, tmr1); /* wait until counter reg is loaded */ do { /* Latch count for reading */ outb_p(SC1, tmrcmd); a = inb_p(tmr1); b = inb_p(tmr1); } while (b == 0); start_time = jiffies; while (b != 0) { /* Latch count for reading */ outb_p(SC1, tmrcmd); a = inb_p(tmr1); b = inb_p(tmr1); end_time = jiffies; /* Don't wait forever - there may be no card here */ if ((end_time - start_time) > 200) return 0; /* No card found */ } end_time = jiffies; /* 87 jiffies, for a 3.68 mhz clock, half that for a double speed clock */ if ((end_time - start_time) > 65) { return (1); /* PI card found */ } else { /* Faster crystal - tmr0 needs adjusting */ /* Set up counter chip */ /* 500 uS square wave */ outb_p(SC0 | LSB_MSB | MODE3, tmrcmd); outb_p(1844 & 0xFF, tmr0); outb_p(1844 >> 8, tmr0); return (2); /* PI2 card found */ }}static void rts(struct pi_local *lp, int x){ int tc; long br; int cmd; int dummy; /* assumes interrupts are off */ cmd = CTL + lp->base; /* Reprogram BRG and turn on transmitter to send flags */ if (x == ON) { /* Turn Tx ON and Receive OFF */ /* Exints off first to avoid abort int */ wrtscc(lp->cardbase, cmd, R15, 0); wrtscc(lp->cardbase, cmd, R3, Rx8); /* Rx off */ lp->rstate = IDLE; if (cmd & 2) { /* if channel a */ /* Set up for TX dma */ wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB); } else { wrtscc(lp->cardbase, cmd, R1, 0); /* No interrupts */ } if (!lp->clockmode) { if (lp->speed) { /* if internally clocked */ br = lp->speed; /* get desired speed */ tc = (lp->xtal / br) - 2; /* calc 1X BRG divisor */ wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */ wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */ } } wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8 | DTR); /* Transmitter now on */ } else { /* Tx OFF and Rx ON */ lp->tstate = IDLE; wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR); /* TX off */ if (!lp->clockmode) { if (lp->speed) { /* if internally clocked */ /* Reprogram BRG for 32x clock for receive DPLL */ /* BRG off, keep Pclk source */ wrtscc(lp->cardbase, cmd, R14, BRSRC); br = lp->speed; /* get desired speed */ /* calc 32X BRG divisor */ tc = ((lp->xtal / 32) / br) - 2; wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */ wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */ /* SEARCH mode, BRG source */ wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* Enable the BRG */ wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL); } } /* Flush rx fifo */ wrtscc(lp->cardbase, cmd, R3, Rx8); /* Make sure rx is off */ wrtscc(lp->cardbase, cmd, R0, ERR_RES); /* reset err latch */ dummy = rdscc(lp->cardbase, cmd, R1); /* get status byte from R1 */ (void) rdscc(lp->cardbase, cmd, R8); (void) rdscc(lp->cardbase, cmd, R8); (void) rdscc(lp->cardbase, cmd, R8); /* Now, turn on the receiver and hunt for a flag */ wrtscc(lp->cardbase, cmd, R3, RxENABLE | Rx8); lp->rstate = ACTIVE; /* Normal state */ if (cmd & 2) { /* if channel a */ setup_rx_dma(lp); } else { /* reset buffer pointers */ lp->rcp = lp->rcvbuf->data; lp->rcvbuf->cnt = 0; wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB)); } wrtscc(lp->cardbase, cmd, R15, BRKIE); /* allow ABORT int */ }}static void scc_init(struct device *dev){ unsigned long flags; struct pi_local *lp = (struct pi_local *) dev->priv; int tc; long br; register int cmd; /* Initialize 8530 channel for SDLC operation */ cmd = CTL + lp->base; save_flags(flags); cli(); switch (cmd & CHANA) { case CHANA: wrtscc(lp->cardbase, cmd, R9, CHRA); /* Reset channel A */ wrtscc(lp->cardbase, cmd, R2, 0xff); /* Initialize interrupt vector */ break; default: wrtscc(lp->cardbase, cmd, R9, CHRB); /* Reset channel B */ break; } /* Deselect all Rx and Tx interrupts */ wrtscc(lp->cardbase, cmd, R1, 0); /* Turn off external interrupts (like CTS/CD) */ wrtscc(lp->cardbase, cmd, R15, 0); /* X1 clock, SDLC mode */ wrtscc(lp->cardbase, cmd, R4, SDLC | X1CLK); /* Tx/Rx parameters */ if (lp->speed) { /* Use internal clocking */ wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI); if (!lp->clockmode) /* Tx Clk from BRG. Rcv Clk from DPLL, TRxC pin outputs DPLL */ wrtscc(lp->cardbase, cmd, R11, TCBR | RCDPLL | TRxCDP | TRxCOI); else /* Tx Clk from DPLL, Rcv Clk from DPLL, TRxC Outputs BRG */ wrtscc(lp->cardbase, cmd, R11, TCDPLL | RCDPLL | TRxCBR | TRxCOI); } else { /* Use external clocking */ wrtscc(lp->cardbase, cmd, R10, CRCPS); /* Tx Clk from Trxcl. Rcv Clk from Rtxcl, TRxC pin is input */ wrtscc(lp->cardbase, cmd, R11, TCTRxCP); } /* Null out SDLC start address */ wrtscc(lp->cardbase, cmd, R6, 0); /* SDLC flag */ wrtscc(lp->cardbase, cmd, R7, FLAG); /* Set up the Transmitter but don't enable it * DTR, 8 bit TX chars only */ wrtscc(lp->cardbase, cmd, R5, Tx8 | DTR); /* Receiver initial setup */ wrtscc(lp->cardbase, cmd, R3, Rx8); /* 8 bits/char */ /* Setting up BRG now - turn it off first */ wrtscc(lp->cardbase, cmd, R14, BRSRC); /* BRG off, keep Pclk source */ /* set the 32x time constant for the BRG in Receive mode */ if (lp->speed) { br = lp->speed; /* get desired speed */ tc = ((lp->xtal / 32) / br) - 2; /* calc 32X BRG divisor */ } else { tc = 14; } wrtscc(lp->cardbase, cmd, R12, tc & 0xFF); /* lower byte */ wrtscc(lp->cardbase, cmd, R13, (tc >> 8) & 0xFF); /* upper byte */ /* Following subroutine sets up and ENABLES the receiver */ rts(lp, OFF); /* TX OFF and RX ON */ if (lp->speed) { /* DPLL frm BRG, BRG src PCLK */ wrtscc(lp->cardbase, cmd, R14, BRSRC | SSBR); } else { /* DPLL frm rtxc,BRG src PCLK */ wrtscc(lp->cardbase, cmd, R14, BRSRC | SSRTxC); } wrtscc(lp->cardbase, cmd, R14, BRSRC | SEARCH); /* SEARCH mode, keep BRG src */ wrtscc(lp->cardbase, cmd, R14, BRSRC | BRENABL); /* Enable the BRG */ if (!(cmd & 2)) /* if channel b */ wrtscc(lp->cardbase, cmd, R1, (INT_ALL_Rx | EXT_INT_ENAB)); wrtscc(lp->cardbase, cmd, R15, BRKIE); /* ABORT int */ /* Now, turn on the receiver and hunt for a flag */ wrtscc(lp->cardbase, cmd, R3, RxENABLE | RxCRC_ENAB | Rx8); restore_flags(flags);}static void chipset_init(struct device *dev){ int cardbase; unsigned long flags; cardbase = dev->base_addr & 0x3f0; save_flags(flags); cli(); wrtscc(cardbase, dev->base_addr + CTL, R9, FHWRES); /* Hardware reset */ /* Disable interrupts with master interrupt ctrl reg */ wrtscc(cardbase, dev->base_addr + CTL, R9, 0); restore_flags(flags);}__initfunc(int pi_init(void)){ int *port; int ioaddr = 0; int card_type = 0; int ports[] = {0x380, 0x300, 0x320, 0x340, 0x360, 0x3a0, 0}; printk(KERN_INFO "PI: V0.8 ALPHA April 23 1995 David Perry (dp@hydra.carleton.ca)\n"); /* Only one card supported for now */ for (port = &ports[0]; *port && !card_type; port++) { ioaddr = *port; if (check_region(ioaddr, PI_TOTAL_SIZE) == 0) { printk(KERN_INFO "PI: Probing for card at address %#3x\n",ioaddr); card_type = hw_probe(ioaddr); } } switch (card_type) { case 1: printk(KERN_INFO "PI: Found a PI card at address %#3x\n", ioaddr); break; case 2: printk(KERN_INFO "PI: Found a PI2 card at address %#3x\n", ioaddr); break; default: printk(KERN_ERR "PI: ERROR: No card found\n"); return -EIO; } /* Link a couple of device structures into the chain */ /* For the A port */ /* Allocate space for 4 buffers even though we only need 3, because one of them may cross a DMA page boundary and be rejected by get_dma_buffer(). */ register_netdev(&pi0a); pi0a.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA); pi0a.dma = PI_DMA; pi0a.base_addr = ioaddr + 2; pi0a.irq = 0; /* And the B port */ register_netdev(&pi0b); pi0b.base_addr = ioaddr; pi0b.irq = 0; pi0b.priv = kmalloc(sizeof(struct pi_local) + (DMA_BUFF_SIZE + sizeof(struct mbuf)) * 4, GFP_KERNEL | GFP_DMA); /* Now initialize them */ pi_probe(&pi0a, card_type); pi_probe(&pi0b, card_type); pi0b.irq = pi0a.irq; /* IRQ is shared */ return 0;}static int valid_dma_page(unsigned long addr, unsigned long dev_buffsize){ if (((addr & 0xffff) + dev_buffsize) <= 0x10000) return 1; else return 0;}static int pi_set_mac_address(struct device *dev, void *addr){ struct sockaddr *sa = (struct sockaddr *)addr; memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); /* addr is an AX.25 shifted ASCII */ return 0; /* mac address */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -