static void vgareset(void) { /* reserve the 'standard' vga registers */ if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0) panic("vga ports already allocated"); if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0) panic("vga ports already allocated"); addarchfile("realmodemem", 0660, rmemread, rmemwrite); }
static void vgareset(void) { /* reserve the 'standard' vga registers */ if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0) panic("vga ports already allocated"); if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0) panic("vga ports already allocated"); conf.monitor = 1; }
void kbdenable(void) { if(kbdq == nil){ kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); } ioalloc(Data, 1, 0, "kbd"); ioalloc(Cmd, 1, 0, "kbd"); intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd"); }
static Uart* uartpci(int ctlrno, Pcidev* p, int barno, int n, int freq, char* name) { int i, io; void *ctlr; char buf[64]; Uart *head, *uart; io = p->mem[barno].bar & ~0x01; snprint(buf, sizeof(buf), "%s%d", pciphysuart.name, ctlrno); if(ioalloc(io, p->mem[barno].size, 0, buf) < 0){ print("uartpci: I/O 0x%uX in use\n", io); return nil; } head = uart = malloc(sizeof(Uart)*n); for(i = 0; i < n; i++){ ctlr = i8250alloc(io, p->intl, p->tbdf); io += 8; if(ctlr == nil) continue; uart->regs = ctlr; snprint(buf, sizeof(buf), "%s.%8.8uX", name, p->tbdf); kstrdup(&uart->name, buf); uart->freq = freq; uart->phys = &i8250physuart; if(uart != head) (uart-1)->next = uart; uart++; } return head; }
void ioinit(void) { int i; char *excluded = ""; panic("Akaros doesn't do IO port allocation yet. Don't init."); for (i = 0; i < ARRAY_SIZE(iomap.maps) - 1; i++) iomap.maps[i].next = &iomap.maps[i + 1]; iomap.maps[i].next = NULL; iomap.free = iomap.maps; char *s; s = excluded; while (s && *s != '\0' && *s != '\n') { char *ends; int io_s, io_e; io_s = (int)strtol(s, &ends, 0); if (ends == NULL || ends == s || *ends != '-') { printd("ioinit: cannot parse option string\n"); break; } s = ++ends; io_e = (int)strtol(s, &ends, 0); if (ends && *ends == ',') *ends++ = '\0'; s = ends; ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated"); } }
static Uart* i8250pnp(void) { int i; Ctlr *ctlr; Uart *head, *uart; head = i8250uart; for(i = 0; i < nelem(i8250uart); i++){ /* * Does it exist? * Should be able to write/read the Scratch Pad * and reserve the I/O space. */ uart = &i8250uart[i]; ctlr = uart->regs; csr8o(ctlr, Scr, 0x55); if(csr8r(ctlr, Scr) == 0x55) continue; if(ioalloc(ctlr->io, 8, 0, uart->name) < 0) continue; if(uart == head) head = uart->next; else (uart-1)->next = uart->next; } return head; }
static Uart* uartisa(int ctlrno, ISAConf* isa) { int io; void *ctlr; Uart *uart; char buf[64]; io = isa->port; snprint(buf, sizeof(buf), "%s%d", isaphysuart.name, ctlrno); if(ioalloc(io, 8, 0, buf) < 0) { print("uartisa: I/O 0x%uX in use\n", io); return nil; } uart = malloc(sizeof(Uart)); ctlr = i8250alloc(io, isa->irq, BUSUNKNOWN); if(uart == nil || ctlr == nil) { iofree(io); free(uart); free(ctlr); return nil; } uart->regs = ctlr; snprint(buf, sizeof(buf), "COM%d", ctlrno+1); kstrdup(&uart->name, buf); uart->freq = isa->freq; uart->phys = &i8250physuart; return uart; }
static Vdev* viopnpdevs(int typ) { Vdev *vd, *h, *t; Pcidev *p; int n, i; h = t = nil; for(p = nil; p = pcimatch(p, 0, 0);){ if(p->vid != 0x1AF4) continue; if((p->did < 0x1000) || (p->did >= 0x1040)) continue; if(p->rid != 0) continue; if(pcicfgr16(p, 0x2E) != typ) continue; if((vd = malloc(sizeof(*vd))) == nil){ print("virtio: no memory for Vdev\n"); break; } vd->port = p->mem[0].bar & ~0x1; if(ioalloc(vd->port, p->mem[0].size, 0, "virtio") < 0){ print("virtio: port %lux in use\n", vd->port); free(vd); continue; } vd->typ = typ; vd->pci = p; /* reset */ outb(vd->port+Status, 0); vd->feat = inl(vd->port+Devfeat); outb(vd->port+Status, Acknowledge|Driver); for(i=0; i<nelem(vd->queue); i++){ outs(vd->port+Qselect, i); n = ins(vd->port+Qsize); if(n == 0 || (n & (n-1)) != 0) break; if((vd->queue[i] = mkvqueue(n)) == nil) break; coherence(); outl(vd->port+Qaddr, PADDR(vd->queue[i]->desc)/BY2PG); } vd->nqueue = i; if(h == nil) h = vd; else t->next = vd; t = vd; } return h; }
void ioinit(void) { char *excluded; int i; for(i = 0; i < nelem(iomap.maps)-1; i++) iomap.maps[i].next = &iomap.maps[i+1]; iomap.maps[i].next = nil; iomap.free = iomap.maps; /* * This is necessary to make the IBM X20 boot. * Have not tracked down the reason. * i82557 is at 0x1000, the dummy entry is needed for swappable devs. */ ioalloc(0x0fff, 1, 0, "dummy"); if ((excluded = getconf("ioexclude")) != nil) { char *s; s = excluded; while (s && *s != '\0' && *s != '\n') { char *ends; int io_s, io_e; io_s = (int)strtol(s, &ends, 0); if (ends == nil || ends == s || *ends != '-') { print("ioinit: cannot parse option string\n"); break; } s = ++ends; io_e = (int)strtol(s, &ends, 0); if (ends && *ends == ',') *ends++ = '\0'; s = ends; ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated"); } } }
void ioinit(void) { char *excluded; int i; for(i = 0; i < nelem(iomap.maps)-1; i++) iomap.maps[i].next = &iomap.maps[i+1]; iomap.maps[i].next = nil; iomap.free = iomap.maps; /* * Someone needs to explain why this was here... */ ioalloc(0x0fff, 1, 0, "dummy"); // i82557 is at 0x1000, the dummy // entry is needed for swappable devs. if (0) {// (excluded = getconf("ioexclude")) != nil) { char *s; s = excluded; while (s && *s != '\0' && *s != '\n') { char *ends; int io_s, io_e; io_s = (int)strtol(s, &ends, 0); if (ends == nil || ends == s || *ends != '-') { print("ioinit: cannot parse option string\n"); break; } s = ++ends; io_e = (int)strtol(s, &ends, 0); if (ends && *ends == ',') *ends++ = '\0'; s = ends; ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated"); } } }
void kbdinit(void) { int c; kbdq = qopen(4*1024, 0, 0, 0); if(kbdq == nil) panic("kbdinit"); qnoblock(kbdq, 1); ioalloc(Data, 1, 0, "kbd"); ioalloc(Cmd, 1, 0, "kbd"); intrenable(IrqKBD, i8042intr, 0, BUSUNKNOWN, "kbd"); /* wait for a quiescent controller */ while((c = inb(Status)) & (Outbusy | Inready)) if(c & Inready) inb(Data); /* get current controller command byte */ outb(Cmd, 0x20); if(inready() < 0){ print("kbdinit: can't read ccc\n"); ccc = 0; } else ccc = inb(Data); /* enable kbd xfers and interrupts */ /* disable mouse */ ccc &= ~Ckbddis; ccc |= Csf | Ckbdint | Cscs1; if(outready() < 0) print("kbd init failed\n"); outb(Cmd, 0x60); if(outready() < 0) print("kbd init failed\n"); outb(Data, ccc); outready(); }
void ioinit(void) { int i; for(i = 0; i < nelem(iomap.maps)-1; i++) iomap.maps[i].next = &iomap.maps[i+1]; iomap.maps[i].next = nil; iomap.free = iomap.maps; // a dummy entry at 2^17 ioalloc(0x20000, 1, 0, "dummy"); }
static Chan* lptattach(char *spec) { Chan *c; int i = (spec && *spec) ? strtol(spec, 0, 0) : 1; char name[8]; static int set; if(!set){ outb(lptbase[i-1]+Qpcr, 0); /* turn off interrupts */ set = 1; intrenable(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt"); } if(i < 1 || i > NDEV) error(Ebadarg); if(lptallocd[i-1] == 0){ int ecr; snprint(name, sizeof name, "lpt%d", i-1); if(ioalloc(lptbase[i-1], 3, 0, name) < 0) error("lpt port space in use"); lptallocd[i-1] = 1; /* Detect ECP - if found, put into PS/2 mode to suit style of driver */ ecr = lptbase[i-1] + 0x402; if ((inb(ecr) & 3) == 1) { outb(ecr, 0x34); if (inb(ecr) == 0x35) { outb(ecr, (inb(ecr) & 0x1f) | (1 << 5)); if(ioalloc(ecr, 1, 0, name) < 0) error("lpt ecr port space in use"); } } } c = devattach('L', spec); c->qid.path = Qdir; c->dev = i-1; return c; }
static void acpiioalloc(uint addr, int len) { if(addr != 0) ioalloc(addr, len, 0, "acpi"); }
static int reset(Ether* ether) { ushort buf[16]; ulong port; Dp8390 *ctlr; int i, slot; uchar ea[Eaddrlen], sum, x; Ec2t *ec2t, tmpec2t; /* * Set up the software configuration. * Use defaults for port, irq, mem and size * if not specified. * The manual says 16KB memory, the box * says 32KB. The manual seems to be correct. */ if(ether->port == 0) ether->port = 0x300; if(ether->irq == 0) ether->irq = 9; if(ether->mem == 0) ether->mem = 0x4000; if(ether->size == 0) ether->size = 16*1024; port = ether->port; if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0) return -1; slot = -1; for(ec2t = ec2tpcmcia; ec2t->name != nil; ec2t++){ if((slot = pcmspecial(ec2t->name, ether)) >= 0) break; } if(ec2t->name == nil){ ec2t = &tmpec2t; ec2t->name = nil; ec2t->iochecksum = 0; for(i = 0; i < ether->nopt; i++){ if(cistrncmp(ether->opt[i], "id=", 3) == 0){ ec2t->name = ðer->opt[i][3]; slot = pcmspecial(ec2t->name, ether); } else if(cistrncmp(ether->opt[i], "iochecksum", 10) == 0) ec2t->iochecksum = 1; } } ctlr = malloc(sizeof(Dp8390)); if(ctlr == nil || slot < 0){ iofree(port); free(ctlr); return -1; } ether->ctlr = ctlr; ctlr->width = 2; ctlr->ram = 0; ctlr->port = port; ctlr->data = port+Data; ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz); ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz); ctlr->dummyrr = 0; for(i = 0; i < ether->nopt; i++){ if(cistrcmp(ether->opt[i], "nodummyrr") == 0) ctlr->dummyrr = 0; else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0) ctlr->dummyrr = strtol(ðer->opt[i][8], nil, 0); } /* * Reset the board. This is done by doing a read * followed by a write to the Reset address. */ buf[0] = inb(port+Reset); delay(2); outb(port+Reset, buf[0]); delay(2); /* * Init the (possible) chip, then use the (possible) * chip to read the (possible) PROM for ethernet address * and a marker byte. * Could just look at the DP8390 command register after * initialisation has been tried, but that wouldn't be * enough, there are other ethernet boards which could * match. */ dp8390reset(ether); sum = 0; if(ec2t->iochecksum){ /* * These cards have the ethernet address in I/O space. * There's a checksum over 8 bytes which sums to 0xFF. */ for(i = 0; i < 8; i++){ x = inb(port+0x14+i); sum += x; buf[i] = (x<<8)|x; } } else{ memset(buf, 0, sizeof(buf)); dp8390read(ctlr, buf, 0, sizeof(buf)); if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57) sum = 0xFF; } if(sum != 0xFF){ pcmspecialclose(slot); iofree(ether->port); free(ether->ctlr); return -1; } /* * Stupid machine. Shorts were asked for, * shorts were delivered, although the PROM is a byte array. * Set the ethernet address. */ memset(ea, 0, Eaddrlen); if(memcmp(ea, ether->ea, Eaddrlen) == 0){ for(i = 0; i < sizeof(ether->ea); i++) ether->ea[i] = buf[i]; } dp8390setea(ether); return 0; }
static int reset(Ether* ether) { int i, t, slot; char *type; int port; enum { WantAny, Want10BT, Want10B2 }; int want; uchar ea[6]; char *p; if(ether->irq == 0) ether->irq = 10; if(ether->port == 0) ether->port = 0x240; port = ether->port; if(ioalloc(port, 0x10, 0, "3C589") < 0) return -1; type = nil; slot = -1; for(i = 0; tcmpcmcia[i] != nil; i++){ type = tcmpcmcia[i]; if((slot = pcmspecial(type, ether)) >= 0) break; } if(slot < 0){ iofree(port); return -1; } /* * Read Ethernet address from card memory * on 3C562, but only if the user has not * overridden it. */ memset(ea, 0, sizeof ea); if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) { if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) { for(i = 0; i < 6; i += 2){ t = ea[i]; ea[i] = ea[i+1]; ea[i+1] = t; } memmove(ether->ea, ea, 6); } } /* * Allow user to specify desired media in plan9.ini */ want = WantAny; for(i = 0; i < ether->nopt; i++){ if(cistrncmp(ether->opt[i], "media=", 6) != 0) continue; p = ether->opt[i]+6; if(cistrcmp(p, "10base2") == 0) want = Want10B2; else if(cistrcmp(p, "10baseT") == 0) want = Want10BT; } /* try configuring as a 10BaseT */ if(want==WantAny || want==Want10BT){ if(configASIC(ether, port, xcvr10BaseT) < 0){ pcmspecialclose(slot); iofree(port); return -1; } delay(100); COMMAND(port, SelectRegisterWindow, Wdiagnostic); if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){ COMMAND(port, SelectRegisterWindow, Wop); print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type); return 0; } } /* try configuring as a 10base2 */ if(want==WantAny || want==Want10B2){ COMMAND(port, GlobalReset, 0); if(configASIC(ether, port, xcvr10Base2) < 0){ pcmspecialclose(slot); iofree(port); return -1; } print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type); return 0; } return -1; /* not reached */ }
ILboolean iSetMetadata(ILimage *Image, ILenum IFD, ILenum ID, ILenum Type, ILuint Count, ILuint Size, const void *Data) { ILmeta *Meta = Image->MetaTags; ILmeta *MetaNew; if (Type > IL_EXIF_TYPE_DOUBLE) { iSetError(IL_INVALID_ENUM); return IL_FALSE; } if (ID >= 0x10000) { // ID is a metaID const ILmetaDesc *desc = iGetMetaDesc(ID); if (!desc) return IL_FALSE; IFD = desc->ExifIFD; ID = desc->ExifID; } // TODO: check for valid type? while (Meta) { if (Meta->IFD == IFD && Meta->ID == ID) { ifree(Meta->Data); ifree(Meta->String); Meta->Type = Type; Meta->Length = Count; Meta->Size = Size; Meta->Data = ialloc(Size); memcpy(Meta->Data, Data, Size); if (Meta->Type == IL_EXIF_TYPE_ASCII || ID == 0x9000) { #ifdef _UNICODE Meta->String = iWideFromMultiByte((const char*)Meta->Data); #else Meta->String = iCharStrDup((const char*)Meta->Data); #endif } return IL_TRUE; } if (Meta->Next) { Meta = Meta->Next; } else { break; } } if (IFD != IL_TIFF_IFD0 && IFD != IL_TIFF_IFD1 && IFD != IL_TIFF_IFD_EXIF && IFD != IL_TIFF_IFD_GPS && IFD != IL_TIFF_IFD_INTEROP) { iSetError(IL_INVALID_ENUM); return IL_FALSE; } MetaNew = ioalloc(ILmeta); MetaNew->IFD = IFD; MetaNew->ID = ID; MetaNew->Type = Type; MetaNew->Length = Count; MetaNew->Size = Size; MetaNew->Data = ialloc(Size); MetaNew->Next = Image->MetaTags; memcpy(MetaNew->Data, Data, Size); #ifdef _UNICODE MetaNew->String = iWideFromMultiByte((const char*)Data); #else MetaNew->String = iCharStrDup((const char*)Data); #endif Image->MetaTags = MetaNew; return IL_TRUE; }
static int ne2000reset(Ether* edev) { ushort buf[16]; ulong port; Dp8390 *dp8390; int i; uchar ea[Eaddrlen]; if(edev->port == 0) ne2000pnp(edev); /* * Set up the software configuration. * Use defaults for irq, mem and size * if not specified. * Must have a port, no more default. */ if(edev->port == 0) return -1; if(edev->irq == 0) edev->irq = 2; if(edev->mem == 0) edev->mem = 0x4000; if(edev->size == 0) edev->size = 16*1024; port = edev->port; if(ioalloc(edev->port, 0x20, 0, "ne2000") < 0) return -1; edev->ctlr = malloc(sizeof(Dp8390)); dp8390 = edev->ctlr; if(dp8390 == nil) error(Enomem); dp8390->width = 2; dp8390->ram = 0; dp8390->port = port; dp8390->data = port+Data; dp8390->tstart = HOWMANY(edev->mem, Dp8390BufSz); dp8390->pstart = dp8390->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); dp8390->pstop = dp8390->tstart + HOWMANY(edev->size, Dp8390BufSz); dp8390->dummyrr = 1; for(i = 0; i < edev->nopt; i++){ if(strcmp(edev->opt[i], "nodummyrr")) continue; dp8390->dummyrr = 0; break; } /* * Reset the board. This is done by doing a read * followed by a write to the Reset address. */ buf[0] = inb(port+Reset); delay(2); outb(port+Reset, buf[0]); delay(2); /* * Init the (possible) chip, then use the (possible) * chip to read the (possible) PROM for ethernet address * and a marker byte. * Could just look at the DP8390 command register after * initialisation has been tried, but that wouldn't be * enough, there are other ethernet boards which could * match. * Parallels has buf[0x0E] == 0x00 whereas real hardware * usually has 0x57. */ dp8390reset(edev); memset(buf, 0, sizeof(buf)); dp8390read(dp8390, buf, 0, sizeof(buf)); i = buf[0x0E] & 0xFF; if((i != 0x00 && i != 0x57) || (buf[0x0F] & 0xFF) != 0x57){ iofree(edev->port); free(edev->ctlr); return -1; } /* * Stupid machine. Shorts were asked for, * shorts were delivered, although the PROM is a byte array. * Set the ethernet address. */ memset(ea, 0, Eaddrlen); if(memcmp(ea, edev->ea, Eaddrlen) == 0){ for(i = 0; i < sizeof(edev->ea); i++) edev->ea[i] = buf[i]; } dp8390setea(edev); return 0; }
void i8259init(void) { int x; ioalloc(Int0ctl, 2, 0, "i8259.0"); ioalloc(Int1ctl, 2, 0, "i8259.1"); ilock(&i8259lock); /* * Set up the first 8259 interrupt processor. * Make 8259 interrupts start at CPU vector VectorPIC. * Set the 8259 as master with edge triggered * input with fully nested interrupts. */ outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered, ICW4 will be sent */ outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */ /* * Set up the second 8259 interrupt processor. * Make 8259 interrupts start at CPU vector VectorPIC+8. * Set the 8259 as slave with edge triggered * input with fully nested interrupts. */ outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered, ICW4 will be sent */ outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */ outb(Int1aux, (i8259mask>>8) & 0xFF); /* * pass #2 8259 interrupts to #1 */ i8259mask &= ~0x04; outb(Int0aux, i8259mask & 0xFF); /* * Set Ocw3 to return the ISR when ctl read. * After initialisation status read is set to IRR. * Read IRR first to possibly deassert an outstanding * interrupt. */ inb(Int0ctl); outb(Int0ctl, Ocw3|0x03); inb(Int1ctl); outb(Int1ctl, Ocw3|0x03); /* * Check for Edge/Level register. * This check may not work for all chipsets. * First try a non-intrusive test - the bits for * IRQs 13, 8, 2, 1 and 0 must be edge (0). If * that's OK try a R/W test. */ x = (inb(Elcr2)<<8)|inb(Elcr1); if(!(x & 0x2107)){ outb(Elcr1, 0); if(inb(Elcr1) == 0){ outb(Elcr1, 0x20); if(inb(Elcr1) == 0x20) i8259elcr = x; outb(Elcr1, x & 0xFF); print("ELCR: %4.4uX\n", i8259elcr); } } iunlock(&i8259lock); }
void rtcinit(void) { if(ioalloc(Paddr, 2, 0, "rtc/nvr") < 0) panic("rtcinit: ioalloc failed"); }
/* * set up for slot cards */ void devi82365link(void) { static int already; int i, j; I82365 *cp; PCMslot *pp; char buf[32], *p; if(already) return; already = 1; if((p=getconf("pcmcia0")) && strncmp(p, "disabled", 8)==0) return; if(_pcmspecial) return; /* look for controllers if the ports aren't already taken */ if(ioalloc(0x3E0, 2, 0, "i82365.0") >= 0){ i82365probe(0x3E0, 0x3E1, 0); i82365probe(0x3E0, 0x3E1, 1); if(ncontroller == 0) iofree(0x3E0); } if(ioalloc(0x3E2, 2, 0, "i82365.1") >= 0){ i = ncontroller; i82365probe(0x3E2, 0x3E3, 0); i82365probe(0x3E2, 0x3E3, 1); if(ncontroller == i) iofree(0x3E2); } if(ncontroller == 0) return; _pcmspecial = pcmcia_pcmspecial; _pcmspecialclose = pcmcia_pcmspecialclose; for(i = 0; i < ncontroller; i++) nslot += controller[i]->nslot; slot = xalloc(nslot * sizeof(PCMslot)); lastslot = slot; for(i = 0; i < ncontroller; i++){ cp = controller[i]; print("#y%d: %d slot %s: port 0x%uX irq %d\n", i, cp->nslot, chipname[cp->type], cp->xreg, cp->irq); for(j = 0; j < cp->nslot; j++){ pp = lastslot++; pp->slotno = pp - slot; pp->memlen = 64*MB; pp->base = (cp->dev<<7) | (j<<6); pp->cp = cp; pp->msec = ~0; pp->verstr[0] = 0; slotdis(pp); /* interrupt on status change */ wrreg(pp, Rcscic, (cp->irq<<4) | Fchangeena); rdreg(pp, Rcsc); } /* for card management interrupts */ snprint(buf, sizeof buf, "i82365.%d", i); intrenable(cp->irq, i82365intr, 0, BUSUNKNOWN, buf); } }