ee_init.c,v
来自「TCP-IP红宝书源代码」· C,V 代码 · 共 534 行
C,V
534 行
head 1.3;
access;
symbols;
locks
dls:1.3; strict;
comment @ * @;
1.3
date 97.09.21.19.25.55; author dls; state Dist;
branches;
next 1.2;
1.2
date 95.02.05.21.46.32; author dls; state Broken;
branches;
next 1.1;
1.1
date 94.09.24.01.00.41; author dls; state Works;
branches;
next ;
desc
@@
1.3
log
@pre-3e code
@
text
@/* ee_init.c - ee_init */
#include <conf.h>
#include <kernel.h>
#include <network.h>
#include <i386.h>
#include <ee.h>
#include <q.h>
static unsigned char eeirq[] = {255, 9, 3, 4, 5, 10, 11, 255 };
unsigned char eecf[] = { 0x0c, 0x08, 0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2,
0x00, 0x00, 0x40, 0x00 };
/*------------------------------------------------------------------------
* ee_init - startup initialization of Intel EtherExpress device
*------------------------------------------------------------------------
*/
int
ee_init(pdev)
struct devsw *pdev;
{
struct etdev *ped;
unsigned short eedat, wtmp, *pw;
unsigned char irq, tmp, memc, mempc, memdec;
int i, offset, ee_int();
unsigned char *pdbuf;
unsigned short rom[64];
struct cbl *pcbl;
struct iscp *piscp;
struct scb *pscb;
struct rfd *prfd;
struct rbd *prbd;
struct tbd *ptbd;
pdev->dvioblk = (char *) ped = &ee[pdev->dvminor];
ped->ed_pdev = pdev;
ped->ed_outq = newq(ETOUTQSZ, QF_NOWAIT);
ped->ed_ifnum = -1;
ped->ed_descr = "Intel EtherExpress";
ped->ed_mcc = 0;
ped->ed_xpending = 0;
/* read ROM data */
for (i=0; i<EE_ROMSIZE; ++i)
rom[i] = ee_romread(pdev->dvcsr, i);
for (i=0; i<16; ++i)
if ((inb(pdev->dvcsr + AID) & 0xf) != i)
break;
if (i < 16) {
kprintf("ee_init: no EtherExpress at 0x%03x\n", pdev->dvcsr);
return SYSERR;
}
/* set IRQ */
irq = pdev->dvivec - IRQBASE;
for (i=0; i<sizeof(eeirq); ++i)
if (eeirq[i] == irq) {
ped->ed_irq = i;
break;
}
if (i == sizeof(eeirq)) {
kprintf("ee%d: invalid IRQ (%d)\n", pdev->dvminor, irq);
return SYSERR;
} else {
eedat = rom[EE_BOARD];
eedat >>= 13;
if (eeirq[eedat] != irq)
kprintf("ee%d: WARNING ROM IRQ (%d) differs\n",
pdev->dvminor, eeirq[eedat]);
ped->ed_irq = eedat;
irq = eeirq[eedat];
}
set_evec(pdev->dvivec, ee_int);
#ifdef notdef
/*XXX */
/* test & set BUS timing */
tmp = inb(pdev->dvcsr + CONFIG);
outb(pdev->dvcsr + CONFIG, tmp | CONFIG_IOTE);
/* do an I/O for the test */
outb(pdev->dvcsr + RDPTR, 0);
inw(pdev->dvcsr + DXREG);
tmp = inb(pdev->dvcsr + CONFIG);
if (tmp & CONFIG_TOGGLE) {
if (tmp & CONFIG_ICLATE)
tmp &= ~CONFIG_16EN; /* force 8-bit mode */
else
tmp |= CONFIG_ICLATE;
}
tmp &= ~(CONFIG_IOTE|CONFIG_TOGGLE);
outb(pdev->dvcsr + CONFIG, tmp);
#endif
/* "warm up" DRAMS-- requires 16 bytes buf access */
outb(pdev->dvcsr + RDPTR, 0);
for (i=0; i<16; ++i)
inw(pdev->dvcsr + DXREG);
/* set up SCP */
outw(pdev->dvcsr+WRPTR, SCP);
outw(pdev->dvcsr+DXREG, SYSBUS_16); /* 16-bit bus */
outw(pdev->dvcsr+DXREG, 0); /* skip unused words */
outw(pdev->dvcsr+DXREG, 0);
outw(pdev->dvcsr+DXREG, ISCP & 0xffff);
outw(pdev->dvcsr+DXREG, ISCP >> 16);
outb(pdev->dvcsr + EEC, EEC_586R); /* reset 82586 */
outb(pdev->dvcsr + EEC, 0); /* clear reset */
/* set buffer memory map */
eedat = rom[EE_MEM1];
memc = eedat & 0xff;
mempc = eedat >> 8;
memdec = rom[EE_MEM2];
mempc = ~memdec;
tmp = 0x80;
for (i=7; i>=0; --i, tmp >>= 1)
if (memdec & tmp) {
ped->ed_iomem = 0xc0000 + i * 0x4000;
break;
}
if (i < 0) {
ped->ed_iomem = 0xcc000;
kprintf("invalid ROM configuration, setting to iomem %X\n",
ped->ed_iomem);
memdec = 0x8;
memc = 0x1c;
}
#ifdef notdef
/* test and set mempc */
pw = (unsigned short *)0xc0000;
mempc = 0;
for (i=0; i<8; ++i) {
mempc >>= 1;
outb(pdev->dvcsr + CONFIG, CONFIG_MCS16);
wtmp = *pw; /* reference it */
mempc |= inb(pdev->dvcsr + CONFIG) & 0x80;
pw += 8192;
}
outb(pdev->dvcsr + CONFIG, CONFIG_MCS16);
wtmp = *(unsigned short *)0xf0000;
if (inb(pdev->dvcsr + CONFIG) & 0x80)
memc |= MEMC_MCS16;
else
memc &= ~MEMC_MCS16;
#endif
outb(pdev->dvcsr + MEMDEC, memdec);
outb(pdev->dvcsr + MEMC, memc);
outb(pdev->dvcsr + MEMPC, mempc);
for (i=0; i<EP_ALEN/2 ; ++i) {
eedat = rom[EE_EADDR + i];
ped->ed_paddr[EP_ALEN - 2*i -1] = eedat & 0xff;
ped->ed_paddr[EP_ALEN - 2*i -2] = eedat >> 8;
ped->ed_bcast[2*i] = ~0;
ped->ed_bcast[2*i+1] = ~0;
}
kprintf("ee%d: etheraddr %02x:%02x:%02x:%02x:%02x:%02x ",
pdev->dvminor,
ped->ed_paddr[0] & 0xff,
ped->ed_paddr[1] & 0xff,
ped->ed_paddr[2] & 0xff,
ped->ed_paddr[3] & 0xff,
ped->ed_paddr[4] & 0xff,
ped->ed_paddr[5] & 0xff);
kprintf("irq %d iomem %X\n", irq, ped->ed_iomem);
piscp = (struct iscp *) (ped->ed_iomem + ISCP);
piscp->iscp_busy = 1;
piscp->iscp_scboff = SCB;
piscp->iscp_scbbase = 0;
pscb = (struct scb *)(ped->ed_iomem + SCB);
ped->ed_scb = pscb;
bzero(pscb, sizeof(struct scb));
offset = (unsigned int)pscb + sizeof(struct scb);
/* allocate space for a command block */
pcbl = (struct cbl *)offset;
ped->ed_cbl = pcbl;
pcbl->cbl_next = 0xffff;
offset += sizeof(struct cbl);
/* allocate transmit buffer */
ptbd = ped->ed_tbd = (struct tbd *)offset;
ptbd->tbd_count = 0;
ptbd->tbd_eof = 1;
ptbd->tbd_next = H2IO(ped, ptbd);
offset += sizeof(struct tbd);
ped->ed_xmbuf = (unsigned char *)offset;
ptbd->tbd_buf = H2IO(ped, ped->ed_xmbuf);
offset += EDLEN;
/* initialize receive buffers */
ped->ed_rfd = (struct rfd *)offset;
offset += EE_NRX * sizeof(struct rfd);
ped->ed_rbd = (struct rbd *)offset;
offset += EE_NRX * sizeof(struct rbd);
pdbuf = (unsigned char *)offset;
prfd = ped->ed_rfd;
prbd = ped->ed_rbd;
for (i=0; i<EE_NRX; ++i) {
prfd->rfd_status = 0;
prfd->rfd_cmd = 0;
prfd->rfd_next = H2IO(ped, prfd + 1);
prfd->rfd_rbd = H2IO(ped, prbd);
prbd->rbd_count = 0;
prbd->rbd_valid = 0;
prbd->rbd_eof = 0;
prbd->rbd_next = H2IO(ped, prbd + 1);
prbd->rbd_buf = H2IO(ped, pdbuf);
prbd->rbd_size = EDLEN;
prbd->rbd_el = 0;
prfd++;
prbd++;
pdbuf += EDLEN;
}
prfd--; prbd--; /* go back to last one */
prfd->rfd_cmd = EECMD_EL; /* mark end of receive FD list */
prfd->rfd_next = H2IO(ped, ped->ed_rfd);
ped->ed_rfdend = prfd;
prbd->rbd_el = 1;
prbd->rbd_next = H2IO(ped, ped->ed_rbd);
ped->ed_rbdend = prbd;
pscb->scb_rfaoff = H2IO(ped, ped->ed_rfd);
outb(pdev->dvcsr + CAC, 0); /* start the 82586 */
for (i=0; i<200; ++i) {
if (!piscp->iscp_busy)
break;
delay(1);
}
if (i == 200) {
kprintf("ee%d: failed initialization\n", pdev->dvminor);
return SYSERR;
}
for (i=0; i<200; ++i) {
if (pscb->scb_status == STAT_CX|STAT_CNA)
break;
delay(1);
}
if (i == 200) {
kprintf("ee%d: failed status check (status %x)\n",
pdev->dvminor, pscb->scb_status);
return SYSERR;
}
/* configure */
ee_cmd(ped, EECMD_CONFIG, eecf);
ee_ack(ped, pscb->scb_status);
/* set station address */
ee_cmd(ped, EECMD_IASET, ped->ed_paddr);
ee_ack(ped, pscb->scb_status);
/* start frame reception */
ee_wait(ped);
pscb->scb_cmd = (pscb->scb_status & 0xf000) | SCBCMD_RUS;
pscb->scb_status = 0;
outb(pdev->dvcsr + CAC, 0); /* start the 82586 */
outb(pdev->dvcsr+SIRQ, ped->ed_irq | SIRQ_IEN); /* enable interrupts */
return OK;
}
int
eedump(ped)
struct etdev *ped;
{
struct iscp *piscp = (struct iscp *)ped->ed_iomem;
struct scb *pscb = ped->ed_scb;
struct cbl *pcbl = ped->ed_cbl;
struct rfd *prfd = ped->ed_rfd;
struct rbd *prbd = ped->ed_rbd;
struct tbd *ptbd = ped->ed_tbd;
int i;
kprintf("\n\nprfd %X prfdend %X prbd %X prbdend %X ptbd %X\n",
ped->ed_rfd, ped->ed_rfdend, ped->ed_rbd, ped->ed_rbdend,
ped->ed_tbd);
kprintf("ISCP: host %X IO %X busy %x scboff %X scbbase %X\n",
piscp, H2IO(ped, piscp), piscp->iscp_busy, piscp->iscp_scboff,
piscp->iscp_scbbase);
kprintf("SCB: host %X IO %X status %x cmd %x cbloff %x rfaoff %x\n",
pscb, H2IO(ped, pscb),
pscb->scb_status, pscb->scb_cmd, pscb->scb_cbloff,
pscb->scb_rfaoff);
kprintf("SCB: errors: crc %d align %d resource %d over %d\n",
pscb->scb_ecrc, pscb->scb_ealign, pscb->scb_eresource,
pscb->scb_eover);
kprintf("CBL: status %x cmd %x next %x size %d\n", pcbl->cbl_status,
pcbl->cbl_cmd, pcbl->cbl_next, sizeof(struct cbl));
kprintf("TBD: count %d eof %d next %X buf %X\n", ptbd->tbd_count,
ptbd->tbd_eof, ptbd->tbd_next, ptbd->tbd_buf);
for (i=0; i<EE_NRX; ++i) {
kprintf("RFD%d: host %X IO %X status %x cmd %x next %x ",
i, prfd, H2IO(ped, prfd), prfd->rfd_status,
prfd->rfd_cmd, prfd->rfd_next);
kprintf("rbd %x\n", prfd->rfd_rbd);
prfd = (struct rfd *)IO2H(ped, prfd->rfd_next);
}
for (i=0; i<EE_NRX; ++i) {
kprintf("RBD%d: host %X IO %X count %d valid %d eof %d ",
i, prbd, H2IO(ped, prbd), prbd->rbd_count,
prbd->rbd_valid, prbd->rbd_eof);
kprintf("next %x buf %X bsize %d el %d\n",
prbd->rbd_next, prbd->rbd_buf, prbd->rbd_size,
prbd->rbd_el);
prbd = (struct rbd *)IO2H(ped, prbd->rbd_next);
}
kprintf("\n\n");
}
@
1.2
log
@*** empty log message ***
@
text
@a40 2
ped->ed_cmutex = screate(1);
ped->ed_mcset = 0;
d42 1
d81 7
a87 2
outb(pdev->dvcsr + CONFIG, CONFIG_IOTE);
inb(pdev->dvcsr);
d91 1
a91 1
tmp &= ~CONFIG_ICLATE;
d95 1
a95 2
if (tmp & CONFIG_BUS16)
tmp |= CONFIG_16EN;
a96 1
/*XXX*/
a97 1
d122 1
a122 1
mempc = ~memdec;
d250 1
a250 1
DELAY(1);
d259 1
a259 1
DELAY(1);
@
1.1
log
@Initial revision
@
text
@a9 3
#define H2IO(x) ((unsigned short)((char *)(x) - ped->ed_iomem))
#define IO2H(x) (ped->ed_iomem + (int)(x))
a29 1
struct scp *pscp;
d41 3
a43 1
ped->ed_xpending = 0;
d66 1
a66 1
kprintf("ee%d: invalid IRQ (%d)\n", irq);
d199 1
a199 1
ptbd->tbd_next = H2IO(ptbd);
d202 1
a202 1
ptbd->tbd_buf = H2IO(ped->ed_xmbuf);
d217 2
a218 2
prfd->rfd_next = H2IO(prfd + 1);
prfd->rfd_rbd = H2IO(prbd);
d223 2
a224 2
prbd->rbd_next = H2IO(prbd + 1);
prbd->rbd_buf = H2IO(pdbuf);
d235 1
a235 1
prfd->rfd_next = H2IO(ped->ed_rfd);
d239 1
a239 1
prbd->rbd_next = H2IO(ped->ed_rbd);
d242 1
a242 1
pscb->scb_rfaoff = H2IO(ped->ed_rfd);
d287 1
a287 61
ee_cmd(ped, cmd, arg1, arg2, arg3)
struct etdev *ped;
unsigned short cmd;
char *arg1, *arg2, *arg3;
{
struct devsw *pdev = ped->ed_pdev;
struct scb *pscb = ped->ed_scb;
struct cbl *pcbl = ped->ed_cbl;
ee_wait(ped);
/* build command block */
pcbl->cbl_status = 0;
pcbl->cbl_cmd = cmd | EECMD_EL;
switch (cmd & EECMD_MASK) {
case EECMD_CONFIG:
blkcopy(pcbl->cbl_cfg, arg1, CFLEN);
case EECMD_IASET:
blkcopy(pcbl->cbl_addr, arg1, EP_ALEN);
break;
case EECMD_TX:
pcbl->cbl_tbd = H2IO(ped->ed_tbd);
break;
case EECMD_NOP:
break; /* not implemented yet */
}
pscb->scb_cmd = SCBCMD_CUS;
pscb->scb_status = 0;
pscb->scb_cbloff = H2IO(pcbl);
outb(pdev->dvcsr + CAC, 0); /* start the 82586 */
}
ee_wait(ped)
struct etdev *ped;
{
struct devsw *pdev = ped->ed_pdev;
struct scb *pscb = ped->ed_scb;
int i;
for (i=0; i<5000; ++i)
if (!pscb->scb_cmd)
return;
kprintf("ee%d: ee_wait timed out, SCB status %x cmd %x\n",
pdev->dvminor, pscb->scb_status, pscb->scb_cmd);
}
ee_ack(ped, status)
struct etdev *ped;
unsigned short status;
{
struct devsw *pdev = ped->ed_pdev;
struct scb *pscb = ped->ed_scb;
ee_wait(ped);
pscb->scb_cmd = status & 0xf000;
outb(pdev->dvcsr+CAC, 0);
}
d297 1
a297 1
int i, j;
d303 1
a303 1
piscp, H2IO(piscp), piscp->iscp_busy, piscp->iscp_scboff,
d306 1
a306 1
pscb, H2IO(pscb),
d318 2
a319 2
i, prfd, H2IO(prfd), prfd->rfd_status, prfd->rfd_cmd,
prfd->rfd_next);
d321 1
a321 1
prfd = (struct rfd *)IO2H(prfd->rfd_next);
d325 2
a326 2
i, prbd, H2IO(prbd), prbd->rbd_count, prbd->rbd_valid,
prbd->rbd_eof);
d330 1
a330 1
prbd = (struct rbd *)IO2H(prbd->rbd_next);
@
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?