ide_pci.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,713 行 · 第 1/3 页
C
1,713 行
* XXX timing values set here are only good for 30/33MHz buses; should deal * with slower ones too (BTW: you overclock-- you lose) */static intcyrix_5530_dmainit(struct ide_pci_cookie *cookie, struct wdparams *wp, int(*wdcmd)(int, void *), void *wdinfo){ int r; u_long pci_revision; int unitno; int iobase_bm; int unit; /*cookie->unit = 0; */ /* XXX */ unit = cookie->unit; pci_revision = pci_conf_read(cookie->tag, PCI_CLASS_REG) & PCI_REVISION_MASK; unitno = cookie->ctlr * 2 + unit; iobase_bm = cookie->iobase_bm; printf("Setting using 0x%x\n", iobase_bm); if ((cookie->ctlr == 0) && (unit == 0)) /* XXX */ outb(iobase_bm + (unit * 0x10) + BMISTA_PORT, 0xe6); outl(iobase_bm + (unit * 0x10) + 0x20, 0x00040010); outl(iobase_bm + (unit * 0x10) + 0x24, 0x00911030); /* If it's a UDMA drive on a '5530, set it up */ /* * depending on what the drive can do, * set the correct modes, */ printf("wd%d: mw=0x%x, pio=0x%x, pcirev=0x%lx, udma=0x%x\n", unitno, mwdma_mode(wp), pio_mode(wp), pci_revision, udma_mode(wp)); if (/* pci_revision >= 1 && */ udma_mode(wp) >= 2) { /*outl(iobase_bm + 0x20 + (cookie->unit * 16), 0x00100010);*/ outl(iobase_bm + 0x24 + (cookie->unit * 16), 0x00911030); /* * With the Cx5530, drive configuration should come *after* the * controller configuration, to make sure the controller sees * the command and does the right thing. */ /* Set UDMA mode 2 on drive */ if (bootverbose) printf("cyrix_5530_dmainit: setting ultra DMA mode 2\n"); r = wdcmd(WDDMA_UDMA2, wdinfo); if (!r) { printf("cyrix_5530_dmainit: setting DMA mode failed\n"); return 0; } if (bootverbose) cyrix_5530_status(cookie); return 1; } /* otherwise, try and program it for MW DMA mode 2 */ else if (mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4) { /* Set multiword DMA mode 2 on drive */ if (bootverbose) printf("cyrix_5530_dmainit: setting multiword DMA mode 2\n"); r = wdcmd(WDDMA_MDMA2, wdinfo); if (!r) { printf("cyrix_5530_dmainit: setting DMA mode failed\n"); return 0; } /* Configure the controller appropriately for MWDMA mode 2 */ /*outl(iobase_bm + 0x20 + (cookie->unit * 16), 0x00100010);*/ outl(iobase_bm + 0x24 + (cookie->unit * 16), 0x00002020); if (bootverbose) cyrix_5530_status(cookie); return 1; } return 0;}static struct vendor_fns vs_cyrix_5530 = { cyrix_5530_dmainit, cyrix_5530_status};static voidpromise_status(struct ide_pci_cookie *cookie){ pcici_t tag; int i; u_int32_t port0_command, port0_altstatus; u_int32_t port1_command, port1_altstatus; u_int32_t dma_block; u_int32_t lat_and_interrupt; u_int32_t drivetiming; int pa, pb, mb, mc; tag = cookie->tag; port0_command = pci_conf_read(tag, 0x10); port0_altstatus = pci_conf_read(tag, 0x14); port1_command = pci_conf_read(tag, 0x18); port1_altstatus = pci_conf_read(tag, 0x1c); dma_block = pci_conf_read(tag, 0x20); lat_and_interrupt = pci_conf_read(tag, 0x3c); printf("promise_status: port0: 0x%lx, port0_alt: 0x%lx, port1: 0x%lx, port1_alt: 0x%lx\n", (u_long)port0_command, (u_long)port0_altstatus, (u_long)port1_command, (u_long)port1_altstatus); printf( "promise_status: dma control blk address: 0x%lx, int: %d, irq: %d\n", (u_long)dma_block, (u_int)(lat_and_interrupt >> 8) & 0xff, (u_int)lat_and_interrupt & 0xff); for(i=0;i<4;i+=2) { drivetiming = pci_conf_read(tag, 0x60 + i * 4); printf("drivebits%d-%d: %b\n", i, i+1, drivetiming, "\020\05Prefetch\06Iordy\07Errdy\010Sync\025DmaW\026DmaR"); pa = drivetiming & 0xf; pb = (drivetiming >> 8) & 0x1f; mb = (drivetiming >> 13) & 0x7; mc = (drivetiming >> 16) & 0xf; printf("drivetiming%d: pa: 0x%x, pb: 0x%x, mb: 0x%x, mc: 0x%x\n", i, pa, pb, mb, mc); drivetiming = pci_conf_read(tag, 0x60 + (i + 1) * 4); pa = drivetiming & 0xf; pb = (drivetiming >> 8) & 0x1f; mb = (drivetiming >> 13) & 0x7; mc = (drivetiming >> 16) & 0xf; printf("drivetiming%d: pa: 0x%x, pb: 0x%x, mb: 0x%x, mc: 0x%x\n", i + 1, pa, pb, mb, mc); }}static struct vendor_fns vs_promise = { generic_dmainit, promise_status};/* Intel PIIX, PIIX3, and PIIX4 IDE controller subfunctions */static voidintel_piix_dump_drive(char *ctlr, int sitre, int is_piix4, int word40, int word44, int word48, int word4a, int drive){ char *ms; if (!sitre) ms = "master/slave"; else if (drive == 0) ms = "master"; else ms = "slave"; printf("intel_piix_status: %s %s sample = %d, %s recovery = %d\n", ctlr, ms, 5 - ((sitre && drive) ? ((word44 >> 2) & 3) : ((word40 >> 12) & 3)), ms, 4 - ((sitre && drive) ? ((word44 >> 0) & 3) : ((word40 >> 8) & 3))); word40 >>= (drive * 4); printf("intel_piix_status: %s %s fastDMAonly %s, pre/post %s,\n\intel_piix_status: IORDY sampling %s,\n\intel_piix_status: fast PIO %s%s\n", ctlr, (drive == 0) ? "master" : "slave", (word40 & 8) ? "enabled" : "disabled", (word40 & 4) ? "enabled" : "disabled", (word40 & 2) ? "enabled" : "disabled", (word40 & 1) ? "enabled" : "disabled", ((word40 & 9) == 9) ? " (overridden by fastDMAonly)" : "" ); if (is_piix4) printf("intel_piix_status: UltraDMA %s, CT/RP = %d/%d\n", word48 ? "enabled": "disabled", 4 - (word4a & 3), 6 - (word4a & 3));}static voidintel_piix_status(struct ide_pci_cookie *cookie){ int iobase_wd; int unit; int iobase_bm; pcici_t tag; pcidi_t type; int ctlr; u_long word40, word44, word48; int sitre, is_piix4; iobase_wd = cookie->iobase_wd; unit = cookie->unit; iobase_bm = cookie->iobase_bm; tag = cookie->tag; type = cookie->type; ctlr = cookie->ctlr; word40 = pci_conf_read(tag, 0x40); word44 = pci_conf_read(tag, 0x44); word48 = pci_conf_read(tag, 0x48); /* * XXX will not be right for the *next* generation of upward-compatible * intel IDE controllers... */ is_piix4 = pci_conf_read(tag, PCI_CLASS_REG) == 0x71118086; sitre = word40 & 0x4000; switch (ctlr * 2 + unit) { case 0: intel_piix_dump_drive("primary", sitre, is_piix4, word40 & 0xffff, word44 & 0x0f, word48, word48 >> 16, 0); break; case 1: intel_piix_dump_drive("primary", sitre, is_piix4, word40 & 0xffff, word44 & 0x0f, word48 >> 1, word48 >> 20, 1); break; case 2: intel_piix_dump_drive("secondary", sitre, is_piix4, (word40 >> 16) & 0xffff, (word44 >> 4) & 0x0f, word48 >> 2, word48 >> 24, 0); break; case 3: intel_piix_dump_drive("secondary", sitre, is_piix4, (word40 >> 16) & 0xffff, (word44 >> 4) & 0x0f, word48 >> 3, word48 >> 28, 1); break; default: printf("intel_piix_status: bad drive or controller number\n"); }}/* * XXX timing values set hereare only good for 30/33MHz buses; should deal * with slower ones too (BTW: you overclock-- you lose) */static intintel_piix_dmainit(struct ide_pci_cookie *cookie, struct wdparams *wp, int(*wdcmd)(int, void *), void *wdinfo){ int r; /* If it's a UDMA drive and a PIIX4, set it up */ if (cookie->type == 0x71118086 && udma_mode(wp) >= 2) { /* Set UDMA mode 2 on controller */ int unitno, mask, new; if (bootverbose) printf("intel_piix_dmainit: setting ultra DMA mode 2\n"); r = wdcmd(WDDMA_UDMA2, wdinfo); if (!r) { printf("intel_piix_dmainit: setting DMA mode failed\n"); return 0; } unitno = cookie->ctlr * 2 + cookie->unit; mask = (1 << unitno) + (3 << (16 + unitno * 4)); new = (1 << unitno) + (2 << (16 + unitno * 4)); pci_conf_write(cookie->tag, 0x48, (pci_conf_read(cookie->tag, 0x48) & ~mask) | new); if (bootverbose) intel_piix_status(cookie); return 1; } /* * if it's an 82371FB, which can't do independent programming of * drive timing, we punt; we're not going to fuss with trying to * coordinate timing modes between drives. if this is you, get a * new motherboard. or contribute patches :) * * we do now at least see if the modes set are OK to use. this should * satisfy the majority of people, with mwdma mode2 drives. */ else if (cookie->type == 0x12308086) { u_long word40; /* can drive do PIO 4 and MW DMA 2? */ if (!(mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4)) return 0; word40 = pci_conf_read(cookie->tag, 0x40); word40 >>= cookie->ctlr * 16; /* Check for timing config usable for DMA on controller */ if (!((word40 & 0x3300) == 0x2300 && ((word40 >> (cookie->unit * 4)) & 1) == 1)) return 0; /* Set multiword DMA mode 2 on drive */ if (bootverbose) printf("intel_piix_dmainit: setting multiword DMA mode 2\n"); r = wdcmd(WDDMA_MDMA2, wdinfo); if (!r) { printf("intel_piix_dmainit: setting DMA mode failed\n"); return 0; } return 1; } /* otherwise, treat it as a PIIX3 and program it for MW DMA mode 2 */ else if (mwdma_mode(wp) >= 2 && pio_mode(wp) >= 4) { u_long mask40, mask44, new40, new44; /* * If SITRE is not set, set it and copy the * appropriate bits into the secondary registers. Do * both controllers at once. */ if (((pci_conf_read(cookie->tag, 0x40) >> (16 * cookie->ctlr)) & 0x4000) == 0) { unsigned int word40, word44; word40 = pci_conf_read(cookie->tag, 0x40); /* copy bits to secondary register */ word44 = pci_conf_read(cookie->tag, 0x44); /* * I've got a Biostar motherboard with Award * BIOS that sets SITRE and secondary timing * on one controller but not the other. * Bizarre. */ if ((word40 & 0x4000) == 0) { word44 &= ~0xf; word44 |= ((word40 & 0x3000) >> 10) | ((word40 & 0x0300) >> 8); } if ((word40 & 0x40000000) == 0) { word44 &= ~0xf0; word44 |= ((word40 & 0x30000000) >> 22) | ((word40 & 0x03000000) >> 20); } /* set SITRE */ word40 |= 0x40004000; pci_conf_write(cookie->tag, 0x40, word40); pci_conf_write(cookie->tag, 0x44, word44); } /* Set multiword DMA mode 2 on drive */ if (bootverbose) printf("intel_piix_dmainit: setting multiword DMA mode 2\n"); r = wdcmd(WDDMA_MDMA2, wdinfo); if (!r) { printf("intel_piix_dmainit: setting DMA mode failed\n"); return 0; } /* * backward compatible hardware leaves us with such * twisted masses of software (aka twiddle the * extremely weird register layout on a PIIX3, setting * PIO mode 4 and MWDMA mode 2) */ if (cookie->unit == 0) { mask40 = 0x330f; new40 = 0x2307; mask44 = 0; new44 = 0; } else { mask40 = 0x00f0; new40 = 0x0070; mask44 = 0x000f; new44 = 0x000b; } if (cookie->ctlr) { mask40 <<= 16; new40 <<= 16; mask44 <<= 4; new44 <<= 4; } pci_conf_write(cookie->tag, 0x40, (pci_conf_read(cookie->tag, 0x40) & ~mask40) | new40); pci_conf_write(cookie->tag, 0x44, (pci_conf_read(cookie->tag, 0x44) & ~mask44) | new44); if (bootverbose) intel_piix_status(cookie); return 1; } return 0;}static struct vendor_fns vs_intel_piix = { intel_piix_dmainit, intel_piix_status};static voidacer_status(struct ide_pci_cookie *cookie) { /* XXX does not do anything right now */}static intacer_dmainit(struct ide_pci_cookie *cookie, struct wdparams *wp, int(*wdcmd)(int, void *), void *wdinfo){ /* Acer Aladdin DMA setup code. UDMA looks to be sinfully easy to set on this thing - just one register. */ u_long word54 = pci_conf_read(cookie->tag, 0x54); /* Set the default Acer FIFO settings (0x55 = 13-word depth and slave operation mode 1) */ word54 |= 0x5555; /* Is this drive UDMA? Set it up if so... */ if(udma_mode(wp) >= 2) { /* This is really easy to do. Just write 0xa (enable UDMA mode with 2T timing) into the word at the right places. */ word54 |= (0xA << (16 + (cookie->ctlr * 8) + (cookie->unit * 4))); /* Now set the drive for UDMA2. */ if(!wdcmd(WDDMA_UDMA2, wdinfo)) { printf("acer_dmainit: could not set UDMA2 mode on wdc%d:%d!\n", cookie->ctlr, cookie->unit); return 0; } /* Write the new config into the registers. I'm not sure if I'm doing this in the right order. */ pci_conf_write(cookie->tag, 0x54, word54); } else if(mwdma_mode(wp) >= 2 && pio_mode(wp) >=4) { /* Otherwise, we're already set for regular DMA. */ if(!wdcmd(WDDMA_MDMA2, wdinfo)) { printf("acer_dmainit: could not set MWDMA2 mode on wdc%d:%d!\n", cookie->ctlr, cookie->unit); return 0; } return 1; } return 0;} static struct vendor_fns vs_acer = { acer_dmainit, acer_status}; /* Generic SFF-8038i code-- all code below here, except for PCI probes, * more or less conforms to the SFF-8038i spec as extended for PCI. * There should be no code that goes beyond that feature set below. *//* XXX mkcookie is overloaded with too many parameters */static struct ide_pci_cookie *mkcookie(int iobase_wd, int ctlr, int unit, int iobase_bm, pcici_t tag, pcidi_t type, struct vendor_fns *vp, int altiobase_wd){ struct ide_pci_cookie *cp; cp = malloc(sizeof *cp, M_DEVBUF, M_NOWAIT); if (!cp) return 0; cp->iobase_wd = iobase_wd; cp->ctlr = ctlr; cp->unit = unit; cp->tag = tag; cp->type = type; cp->iobase_bm = iobase_bm; cp->altiobase_wd = altiobase_wd; bcopy(vp, &cp->vs, sizeof(struct vendor_fns)); if (!prdbuf) { prdbuf = malloc(PRD_ALLOC_SIZE, M_DEVBUF, M_NOWAIT); if (!prdbuf) { FREE(cp, M_DEVBUF); return 0; } if (((int)prdbuf >> PAGE_SHIFT) ^ (((int)prdbuf + PRD_ALLOC_SIZE - 1) >> PAGE_SHIFT)) { printf("ide_pci: prdbuf straddles page boundary, no DMA\n"); FREE(cp, M_DEVBUF); FREE(prdbuf, M_DEVBUF); return 0; } prdbuf_next = prdbuf; } if (((char *)prdbuf_next + PRD_BUF_SIZE) > ((char *)prdbuf + PRD_ALLOC_SIZE)) { printf("ide_pci: mkcookie %04x:%d: no more space for PRDs, no DMA\n", iobase_wd, unit); FREE(cp, M_DEVBUF); return 0; } cp->prd = prdbuf_next; (char *)prdbuf_next += PRD_BUF_SIZE;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?