From: deraadt Date: Tue, 28 Nov 1995 16:15:42 +0000 (+0000) Subject: i386 isa bounce buffers by hannken@eis.cs.tu-bs.de X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=fd335a0b7f63ede464e54df371a6eb533cbd8d45;p=openbsd i386 isa bounce buffers by hannken@eis.cs.tu-bs.de ultra14f does not bounce properly yet. --- diff --git a/sys/dev/isa/aha.c b/sys/dev/isa/aha.c index a15a51b5b6f..d516a8d6421 100644 --- a/sys/dev/isa/aha.c +++ b/sys/dev/isa/aha.c @@ -1,5 +1,4 @@ /* $NetBSD: aha1542.c,v 1.53 1995/10/03 20:58:56 mycroft Exp $ */ - /* * Copyright (c) 1994 Charles Hannum. All rights reserved. * @@ -50,6 +49,7 @@ #include #include +#include #include #include #include @@ -63,6 +63,7 @@ #include #include +#include #include #include @@ -70,6 +71,21 @@ #define Debugger() panic("should call debugger here (aha1542.c)") #endif /* ! DDB */ +/* XXX fixme: */ +/* on i386 at least xfers from/to user memory */ +/* cannot be serviced at interrupt time. */ +#ifdef i386 +#include +#define VOLATILE_XS(xs) \ + ((xs)->datalen > 0 && \ + ((vm_offset_t)((xs)->data) < VM_MIN_KERNEL_ADDRESS) && \ + ((xs)->flags & SCSI_POLL) == 0) +#else +#define VOLATILE_XS(xs) 0 +#endif + +#undef TUNE_1542 /* if bus speed check breaks the machine, undefine it */ + /************************** board definitions *******************************/ /* @@ -184,7 +200,7 @@ struct aha_mbx { /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */ #define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */ - /* allow 64 K i/o (min) */ + /* allow 60 K i/o (min) */ struct aha_ccb { u_char opcode; @@ -207,16 +223,19 @@ struct aha_ccb { u_char seg_len[3]; u_char seg_addr[3]; } scat_gath[AHA_NSEG]; +#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain) /*----------------------------------------------------------------*/ TAILQ_ENTRY(aha_ccb) chain; struct aha_ccb *nexthash; - long hashkey; struct scsi_xfer *xs; /* the scsi_xfer for this cmd */ int flags; #define CCB_FREE 0 #define CCB_ACTIVE 1 #define CCB_ABORTED 2 struct aha_mbx_out *mbx; /* pointer to mail box */ + struct isadma_seg ccb_phys[1]; /* phys segment of this ccb */ + struct isadma_seg data_phys[AHA_NSEG]; /* phys segments of data */ + int data_nseg; }; /* @@ -302,8 +321,6 @@ struct aha_extbios { /*********************************** end of board definitions***************/ -#define KVTOPHYS(x) vtophys(x) - #ifdef AHADEBUG int aha_debug = 1; #endif /*AHADEBUG */ @@ -549,7 +566,7 @@ ahaprint(aux, name) void *aux; char *name; { - if (name != NULL) + if (name != NULL) printf("%s: scsibus ", name); return UNCONF; } @@ -566,7 +583,7 @@ ahaattach(parent, self, aux) struct aha_softc *aha = (void *)self; if (ia->ia_drq != DRQUNK) - isa_dmacascade(ia->ia_drq); + isadma_cascade(ia->ia_drq); aha_init(aha); TAILQ_INIT(&aha->free_ccb); @@ -727,6 +744,9 @@ aha_free_ccb(aha, ccb, flags) s = splbio(); + if (ccb->ccb_phys[0].addr) + isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys); + ccb->flags = CCB_FREE; TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain); @@ -748,14 +768,6 @@ aha_init_ccb(aha, ccb) int hashnum; bzero(ccb, sizeof(struct aha_ccb)); - /* - * put in the phystokv hash table - * Never gets taken out. - */ - ccb->hashkey = KVTOPHYS(ccb); - hashnum = CCB_HASH(ccb->hashkey); - ccb->nexthash = aha->ccbhash[hashnum]; - aha->ccbhash[hashnum] = ccb; } static inline void @@ -775,10 +787,15 @@ aha_get_ccb(aha, flags) int flags; { struct aha_ccb *ccb; - int s; + int hashnum, mflags, s; s = splbio(); + if (flags & SCSI_NOSLEEP) + mflags = ISADMA_MAP_BOUNCE; + else + mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; + /* * If we can and have to, sleep waiting for one * to come free @@ -809,6 +826,17 @@ aha_get_ccb(aha, flags) aha_reset_ccb(aha, ccb); ccb->flags = CCB_ACTIVE; + if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys, + mflags | ISADMA_MAP_CONTIG) == 1) { + hashnum = CCB_HASH(ccb->ccb_phys[0].addr); + ccb->nexthash = aha->ccbhash[hashnum]; + aha->ccbhash[hashnum] = ccb; + } else { + ccb->ccb_phys[0].addr = 0; + aha_free_ccb(aha, ccb, flags); + ccb = 0; + } + out: splx(s); return (ccb); @@ -823,14 +851,18 @@ aha_ccb_phys_kv(aha, ccb_phys) u_long ccb_phys; { int hashnum = CCB_HASH(ccb_phys); - struct aha_ccb *ccb = aha->ccbhash[hashnum]; + struct aha_ccb *res, **ccb = &aha->ccbhash[hashnum]; - while (ccb) { - if (ccb->hashkey == ccb_phys) + while (*ccb) { + if ((*ccb)->ccb_phys[0].addr == ccb_phys) break; - ccb = ccb->nexthash; + (*ccb) = (*ccb)->nexthash; } - return ccb; + + if (res = *ccb) + *ccb = (*ccb)->nexthash; + + return res; } /* @@ -874,7 +906,7 @@ aha_send_mbo(aha, cmd, ccb) } /* Link ccb to mbo. */ - lto3b(KVTOPHYS(ccb), wmbo->ccb_addr); + lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr); ccb->mbx = wmbo; wmbo->cmd = cmd; @@ -941,6 +973,19 @@ aha_done(aha, ccb) xs->resid = 0; } xs->flags |= ITSDONE; + + if (VOLATILE_XS(xs)) { + wakeup(ccb); + return; + } + + if (ccb->data_nseg) { + if (xs->flags & SCSI_DATA_IN) + isadma_copyfrombuf(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + isadma_unmap(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + } aha_free_ccb(aha, ccb, xs->flags); scsi_done(xs); } @@ -952,7 +997,6 @@ int aha_find(aha) struct aha_softc *aha; { - u_char ad[3]; volatile int i, sts; struct aha_config conf; struct aha_inquire inquire; @@ -1090,16 +1134,6 @@ noinquire: aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7); aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4); -#ifdef TUNE_1542 -#error XXX Must deal with configuring the DRQ channel if we do this. - /* - * Initialize memory transfer speed - * Not compiled in by default because it breaks some machines - */ - if (!aha_set_bus_speed(aha)) - return EIO; -#endif /* TUNE_1542 */ - return 0; } @@ -1111,12 +1145,25 @@ aha_init(aha) struct aha_softc *aha; { u_char ad[3]; + struct isadma_seg mbx_phys[1]; int i; +#ifdef TUNE_1542 /* - * Initialize mail box + * Initialize memory transfer speed + * Not compiled in by default because it breaks some machines + */ + if (!aha_set_bus_speed(aha)) + panic("aha_init: cannot set bus speed"); +#endif /* TUNE_1542 */ + + /* + * Initialize mail box. This mapping will never be undone. */ - lto3b(KVTOPHYS(&aha->aha_mbx), ad); + if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx), + mbx_phys, ISADMA_MAP_CONTIG) != 1) + panic("aha_init: cannot map mail box"); + lto3b(mbx_phys[0].addr, ad); aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE, ad[0], ad[1], ad[2]); @@ -1155,10 +1202,7 @@ aha_scsi_cmd(xs) struct aha_softc *aha = sc_link->adapter_softc; struct aha_ccb *ccb; struct aha_scat_gath *sg; - int seg; /* scatter gather seg being worked on */ - int thiskv; - u_long thisphys, nextphys; - int bytes_this_seg, bytes_this_page, datalen, flags; + int seg, datalen, flags, mflags; struct iovec *iovp; struct aha_mbx_out *mbo; int s; @@ -1170,6 +1214,10 @@ aha_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; + if (flags & SCSI_NOSLEEP) + mflags = ISADMA_MAP_BOUNCE; + else + mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; if ((flags & (ITSDONE|INUSE)) != INUSE) { printf("%s: done or not in use?\n", aha->sc_dev.dv_xname); xs->flags &= ~ITSDONE; @@ -1199,9 +1247,11 @@ aha_scsi_cmd(xs) ccb->req_sense_length = sizeof(ccb->scsi_sense); ccb->host_stat = 0x00; ccb->target_stat = 0x00; + ccb->data_nseg = 0; if (xs->datalen && (flags & SCSI_RESET) == 0) { - lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr); + sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath; + lto3b((vm_offset_t)sg, ccb->data_addr); sg = ccb->scat_gath; seg = 0; #ifdef TFS @@ -1227,73 +1277,25 @@ aha_scsi_cmd(xs) * Set up the scatter gather block */ - SC_DEBUG(sc_link, SDEV_DB4, - ("%d @0x%x:- ", xs->datalen, xs->data)); - datalen = xs->datalen; - thiskv = (int) xs->data; - thisphys = KVTOPHYS(thiskv); - - while (datalen && seg < AHA_NSEG) { - bytes_this_seg = 0; - - /* put in the base address */ - lto3b(thisphys, sg->seg_addr); - - SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys)); - - /* do it at least once */ - nextphys = thisphys; - while (datalen && thisphys == nextphys) { - /* - * This page is contiguous (physically) - * with the the last, just extend the - * length - */ - /* check it fits on the ISA bus */ - if (thisphys > 0xFFFFFF) { - printf("%s: DMA beyond" - " end of ISA\n", - aha->sc_dev.dv_xname); - xs->error = XS_DRIVER_STUFFUP; - aha_free_ccb(aha, ccb, flags); - return COMPLETE; - } - /** how far to the end of the page ***/ - nextphys = (thisphys & ~PGOFSET) + NBPG; - bytes_this_page = nextphys - thisphys; - /**** or the data ****/ - bytes_this_page = min(bytes_this_page, - datalen); - bytes_this_seg += bytes_this_page; - datalen -= bytes_this_page; - - /* get more ready for the next page */ - thiskv = (thiskv & ~PGOFSET) + NBPG; - if (datalen) - thisphys = KVTOPHYS(thiskv); - } - /* - * next page isn't contiguous, finish the seg - */ - SC_DEBUGN(sc_link, SDEV_DB4, - ("(0x%x)", bytes_this_seg)); - lto3b(bytes_this_seg, sg->seg_len); - sg++; - seg++; + ccb->data_nseg = isadma_map(xs->data, xs->datalen, + ccb->data_phys, mflags); + for (seg = 0; seg < ccb->data_nseg; seg++) { + lto3b(ccb->data_phys[seg].addr, + sg[seg].seg_addr); + lto3b(ccb->data_phys[seg].length, + sg[seg].seg_len); } } - lto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length); - SC_DEBUGN(sc_link, SDEV_DB4, ("\n")); - if (datalen) { - /* - * there's still data, must have run out of segs! - */ - printf("%s: aha_scsi_cmd, more than %d dma segs\n", - aha->sc_dev.dv_xname, AHA_NSEG); + lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length); + if (ccb->data_nseg == 0) { + printf("%s: aha_scsi_cmd, cannot map\n", + aha->sc_dev.dv_xname); xs->error = XS_DRIVER_STUFFUP; aha_free_ccb(aha, ccb, flags); return COMPLETE; - } + } else if (flags & SCSI_DATA_OUT) + isadma_copytobuf(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); } else { /* No data xfer, use non S/G values */ lto3b(0, ccb->data_addr); lto3b(0, ccb->data_length); @@ -1309,9 +1311,14 @@ aha_scsi_cmd(xs) s = splbio(); + isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys); + if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) { splx(s); xs->error = XS_DRIVER_STUFFUP; + if (ccb->data_nseg) + isadma_unmap(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); aha_free_ccb(aha, ccb, flags); return TRY_AGAIN_LATER; } @@ -1320,6 +1327,25 @@ aha_scsi_cmd(xs) * Usually return SUCCESSFULLY QUEUED */ SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n")); + + if (VOLATILE_XS(xs)) { + if (tsleep(ccb, PRIBIO, "ahawait", (xs->timeout * hz) / 1000)) { + aha_timeout(ccb); + tsleep(ccb, PRIBIO, "ahawait1", 2000); + } + splx(s); + if (ccb->data_nseg) { + if (flags & SCSI_DATA_IN) + isadma_copyfrombuf(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + isadma_unmap(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + } + aha_free_ccb(aha, ccb, xs->flags); + scsi_done(xs); + return COMPLETE; + } + if ((flags & SCSI_POLL) == 0) { timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000); splx(s); @@ -1402,19 +1428,18 @@ aha_set_bus_speed(aha) lastworking = speed; } if (lastworking == -1) { - printf("no working bus speed\n"); + printf(" no working bus speed"); return 0; } - printf("%d nsec ", aha_bus_speeds[lastworking].nsecs); + printf(", %d nsec ", aha_bus_speeds[lastworking].nsecs); if (lastworking == 7) /* is slowest already */ - printf("marginal\n"); + printf("marginal"); else { lastworking++; - printf("ok, using %d nsec\n", - aha_bus_speeds[lastworking].nsecs); + printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs); } if (!aha_bus_speed_check(aha, lastworking)) { - printf("test retry failed.. aborting.\n"); + printf("test retry failed.. aborting."); return 0; } return 1; @@ -1435,9 +1460,24 @@ aha_bus_speed_check(aha, speed) int speed; { int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed); - int loopcount; + int result, loopcount; + struct isadma_seg test_phys[1], scratch_phys[1]; u_char ad[3]; + result = 1; + + if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf), + scratch_phys, ISADMA_MAP_CONTIG) != 1) + return 0; + if (isadma_map(aha_test_string, sizeof(aha_test_string), + test_phys, ISADMA_MAP_CONTIG) != 1) { + isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); + return 0; + } + isadma_copytobuf(aha_test_string, sizeof(aha_test_string), + 1, test_phys); + /* * Set the dma-speed */ @@ -1448,7 +1488,7 @@ aha_bus_speed_check(aha, speed) * it's address. Read it onto the board */ for (loopcount = 100; loopcount; loopcount--) { - lto3b(KVTOPHYS(aha_test_string), ad); + lto3b(test_phys[0].addr, ad); aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]); /* @@ -1456,9 +1496,13 @@ aha_bus_speed_check(aha, speed) * board. */ bzero(aha_scratch_buf, 54); + isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); - lto3b(KVTOPHYS(aha_scratch_buf), ad); + lto3b(scratch_phys[0].addr, ad); aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]); + isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); /* * Compare the original data and the final data and return the @@ -1466,12 +1510,19 @@ aha_bus_speed_check(aha, speed) * first 54 bytes, because that's all the board copies during * WRITE_FIFO and READ_FIFO. */ - if (bcmp(aha_test_string, aha_scratch_buf, 54)) - return 0; /* failed test */ + if (bcmp(aha_test_string, aha_scratch_buf, 54)) { + result = 0; /* failed test */ + break; + } } + isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); + isadma_unmap(aha_test_string, sizeof(aha_test_string), + 1, test_phys); + /* copy succeeded; assume speed ok */ - return 1; + return result; } #endif /* TUNE_1542 */ diff --git a/sys/dev/isa/aha1542.c b/sys/dev/isa/aha1542.c index a15a51b5b6f..d516a8d6421 100644 --- a/sys/dev/isa/aha1542.c +++ b/sys/dev/isa/aha1542.c @@ -1,5 +1,4 @@ /* $NetBSD: aha1542.c,v 1.53 1995/10/03 20:58:56 mycroft Exp $ */ - /* * Copyright (c) 1994 Charles Hannum. All rights reserved. * @@ -50,6 +49,7 @@ #include #include +#include #include #include #include @@ -63,6 +63,7 @@ #include #include +#include #include #include @@ -70,6 +71,21 @@ #define Debugger() panic("should call debugger here (aha1542.c)") #endif /* ! DDB */ +/* XXX fixme: */ +/* on i386 at least xfers from/to user memory */ +/* cannot be serviced at interrupt time. */ +#ifdef i386 +#include +#define VOLATILE_XS(xs) \ + ((xs)->datalen > 0 && \ + ((vm_offset_t)((xs)->data) < VM_MIN_KERNEL_ADDRESS) && \ + ((xs)->flags & SCSI_POLL) == 0) +#else +#define VOLATILE_XS(xs) 0 +#endif + +#undef TUNE_1542 /* if bus speed check breaks the machine, undefine it */ + /************************** board definitions *******************************/ /* @@ -184,7 +200,7 @@ struct aha_mbx { /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */ #define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */ - /* allow 64 K i/o (min) */ + /* allow 60 K i/o (min) */ struct aha_ccb { u_char opcode; @@ -207,16 +223,19 @@ struct aha_ccb { u_char seg_len[3]; u_char seg_addr[3]; } scat_gath[AHA_NSEG]; +#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain) /*----------------------------------------------------------------*/ TAILQ_ENTRY(aha_ccb) chain; struct aha_ccb *nexthash; - long hashkey; struct scsi_xfer *xs; /* the scsi_xfer for this cmd */ int flags; #define CCB_FREE 0 #define CCB_ACTIVE 1 #define CCB_ABORTED 2 struct aha_mbx_out *mbx; /* pointer to mail box */ + struct isadma_seg ccb_phys[1]; /* phys segment of this ccb */ + struct isadma_seg data_phys[AHA_NSEG]; /* phys segments of data */ + int data_nseg; }; /* @@ -302,8 +321,6 @@ struct aha_extbios { /*********************************** end of board definitions***************/ -#define KVTOPHYS(x) vtophys(x) - #ifdef AHADEBUG int aha_debug = 1; #endif /*AHADEBUG */ @@ -549,7 +566,7 @@ ahaprint(aux, name) void *aux; char *name; { - if (name != NULL) + if (name != NULL) printf("%s: scsibus ", name); return UNCONF; } @@ -566,7 +583,7 @@ ahaattach(parent, self, aux) struct aha_softc *aha = (void *)self; if (ia->ia_drq != DRQUNK) - isa_dmacascade(ia->ia_drq); + isadma_cascade(ia->ia_drq); aha_init(aha); TAILQ_INIT(&aha->free_ccb); @@ -727,6 +744,9 @@ aha_free_ccb(aha, ccb, flags) s = splbio(); + if (ccb->ccb_phys[0].addr) + isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys); + ccb->flags = CCB_FREE; TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain); @@ -748,14 +768,6 @@ aha_init_ccb(aha, ccb) int hashnum; bzero(ccb, sizeof(struct aha_ccb)); - /* - * put in the phystokv hash table - * Never gets taken out. - */ - ccb->hashkey = KVTOPHYS(ccb); - hashnum = CCB_HASH(ccb->hashkey); - ccb->nexthash = aha->ccbhash[hashnum]; - aha->ccbhash[hashnum] = ccb; } static inline void @@ -775,10 +787,15 @@ aha_get_ccb(aha, flags) int flags; { struct aha_ccb *ccb; - int s; + int hashnum, mflags, s; s = splbio(); + if (flags & SCSI_NOSLEEP) + mflags = ISADMA_MAP_BOUNCE; + else + mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; + /* * If we can and have to, sleep waiting for one * to come free @@ -809,6 +826,17 @@ aha_get_ccb(aha, flags) aha_reset_ccb(aha, ccb); ccb->flags = CCB_ACTIVE; + if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys, + mflags | ISADMA_MAP_CONTIG) == 1) { + hashnum = CCB_HASH(ccb->ccb_phys[0].addr); + ccb->nexthash = aha->ccbhash[hashnum]; + aha->ccbhash[hashnum] = ccb; + } else { + ccb->ccb_phys[0].addr = 0; + aha_free_ccb(aha, ccb, flags); + ccb = 0; + } + out: splx(s); return (ccb); @@ -823,14 +851,18 @@ aha_ccb_phys_kv(aha, ccb_phys) u_long ccb_phys; { int hashnum = CCB_HASH(ccb_phys); - struct aha_ccb *ccb = aha->ccbhash[hashnum]; + struct aha_ccb *res, **ccb = &aha->ccbhash[hashnum]; - while (ccb) { - if (ccb->hashkey == ccb_phys) + while (*ccb) { + if ((*ccb)->ccb_phys[0].addr == ccb_phys) break; - ccb = ccb->nexthash; + (*ccb) = (*ccb)->nexthash; } - return ccb; + + if (res = *ccb) + *ccb = (*ccb)->nexthash; + + return res; } /* @@ -874,7 +906,7 @@ aha_send_mbo(aha, cmd, ccb) } /* Link ccb to mbo. */ - lto3b(KVTOPHYS(ccb), wmbo->ccb_addr); + lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr); ccb->mbx = wmbo; wmbo->cmd = cmd; @@ -941,6 +973,19 @@ aha_done(aha, ccb) xs->resid = 0; } xs->flags |= ITSDONE; + + if (VOLATILE_XS(xs)) { + wakeup(ccb); + return; + } + + if (ccb->data_nseg) { + if (xs->flags & SCSI_DATA_IN) + isadma_copyfrombuf(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + isadma_unmap(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + } aha_free_ccb(aha, ccb, xs->flags); scsi_done(xs); } @@ -952,7 +997,6 @@ int aha_find(aha) struct aha_softc *aha; { - u_char ad[3]; volatile int i, sts; struct aha_config conf; struct aha_inquire inquire; @@ -1090,16 +1134,6 @@ noinquire: aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7); aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4); -#ifdef TUNE_1542 -#error XXX Must deal with configuring the DRQ channel if we do this. - /* - * Initialize memory transfer speed - * Not compiled in by default because it breaks some machines - */ - if (!aha_set_bus_speed(aha)) - return EIO; -#endif /* TUNE_1542 */ - return 0; } @@ -1111,12 +1145,25 @@ aha_init(aha) struct aha_softc *aha; { u_char ad[3]; + struct isadma_seg mbx_phys[1]; int i; +#ifdef TUNE_1542 /* - * Initialize mail box + * Initialize memory transfer speed + * Not compiled in by default because it breaks some machines + */ + if (!aha_set_bus_speed(aha)) + panic("aha_init: cannot set bus speed"); +#endif /* TUNE_1542 */ + + /* + * Initialize mail box. This mapping will never be undone. */ - lto3b(KVTOPHYS(&aha->aha_mbx), ad); + if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx), + mbx_phys, ISADMA_MAP_CONTIG) != 1) + panic("aha_init: cannot map mail box"); + lto3b(mbx_phys[0].addr, ad); aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE, ad[0], ad[1], ad[2]); @@ -1155,10 +1202,7 @@ aha_scsi_cmd(xs) struct aha_softc *aha = sc_link->adapter_softc; struct aha_ccb *ccb; struct aha_scat_gath *sg; - int seg; /* scatter gather seg being worked on */ - int thiskv; - u_long thisphys, nextphys; - int bytes_this_seg, bytes_this_page, datalen, flags; + int seg, datalen, flags, mflags; struct iovec *iovp; struct aha_mbx_out *mbo; int s; @@ -1170,6 +1214,10 @@ aha_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; + if (flags & SCSI_NOSLEEP) + mflags = ISADMA_MAP_BOUNCE; + else + mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; if ((flags & (ITSDONE|INUSE)) != INUSE) { printf("%s: done or not in use?\n", aha->sc_dev.dv_xname); xs->flags &= ~ITSDONE; @@ -1199,9 +1247,11 @@ aha_scsi_cmd(xs) ccb->req_sense_length = sizeof(ccb->scsi_sense); ccb->host_stat = 0x00; ccb->target_stat = 0x00; + ccb->data_nseg = 0; if (xs->datalen && (flags & SCSI_RESET) == 0) { - lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr); + sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath; + lto3b((vm_offset_t)sg, ccb->data_addr); sg = ccb->scat_gath; seg = 0; #ifdef TFS @@ -1227,73 +1277,25 @@ aha_scsi_cmd(xs) * Set up the scatter gather block */ - SC_DEBUG(sc_link, SDEV_DB4, - ("%d @0x%x:- ", xs->datalen, xs->data)); - datalen = xs->datalen; - thiskv = (int) xs->data; - thisphys = KVTOPHYS(thiskv); - - while (datalen && seg < AHA_NSEG) { - bytes_this_seg = 0; - - /* put in the base address */ - lto3b(thisphys, sg->seg_addr); - - SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys)); - - /* do it at least once */ - nextphys = thisphys; - while (datalen && thisphys == nextphys) { - /* - * This page is contiguous (physically) - * with the the last, just extend the - * length - */ - /* check it fits on the ISA bus */ - if (thisphys > 0xFFFFFF) { - printf("%s: DMA beyond" - " end of ISA\n", - aha->sc_dev.dv_xname); - xs->error = XS_DRIVER_STUFFUP; - aha_free_ccb(aha, ccb, flags); - return COMPLETE; - } - /** how far to the end of the page ***/ - nextphys = (thisphys & ~PGOFSET) + NBPG; - bytes_this_page = nextphys - thisphys; - /**** or the data ****/ - bytes_this_page = min(bytes_this_page, - datalen); - bytes_this_seg += bytes_this_page; - datalen -= bytes_this_page; - - /* get more ready for the next page */ - thiskv = (thiskv & ~PGOFSET) + NBPG; - if (datalen) - thisphys = KVTOPHYS(thiskv); - } - /* - * next page isn't contiguous, finish the seg - */ - SC_DEBUGN(sc_link, SDEV_DB4, - ("(0x%x)", bytes_this_seg)); - lto3b(bytes_this_seg, sg->seg_len); - sg++; - seg++; + ccb->data_nseg = isadma_map(xs->data, xs->datalen, + ccb->data_phys, mflags); + for (seg = 0; seg < ccb->data_nseg; seg++) { + lto3b(ccb->data_phys[seg].addr, + sg[seg].seg_addr); + lto3b(ccb->data_phys[seg].length, + sg[seg].seg_len); } } - lto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length); - SC_DEBUGN(sc_link, SDEV_DB4, ("\n")); - if (datalen) { - /* - * there's still data, must have run out of segs! - */ - printf("%s: aha_scsi_cmd, more than %d dma segs\n", - aha->sc_dev.dv_xname, AHA_NSEG); + lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length); + if (ccb->data_nseg == 0) { + printf("%s: aha_scsi_cmd, cannot map\n", + aha->sc_dev.dv_xname); xs->error = XS_DRIVER_STUFFUP; aha_free_ccb(aha, ccb, flags); return COMPLETE; - } + } else if (flags & SCSI_DATA_OUT) + isadma_copytobuf(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); } else { /* No data xfer, use non S/G values */ lto3b(0, ccb->data_addr); lto3b(0, ccb->data_length); @@ -1309,9 +1311,14 @@ aha_scsi_cmd(xs) s = splbio(); + isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys); + if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) { splx(s); xs->error = XS_DRIVER_STUFFUP; + if (ccb->data_nseg) + isadma_unmap(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); aha_free_ccb(aha, ccb, flags); return TRY_AGAIN_LATER; } @@ -1320,6 +1327,25 @@ aha_scsi_cmd(xs) * Usually return SUCCESSFULLY QUEUED */ SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n")); + + if (VOLATILE_XS(xs)) { + if (tsleep(ccb, PRIBIO, "ahawait", (xs->timeout * hz) / 1000)) { + aha_timeout(ccb); + tsleep(ccb, PRIBIO, "ahawait1", 2000); + } + splx(s); + if (ccb->data_nseg) { + if (flags & SCSI_DATA_IN) + isadma_copyfrombuf(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + isadma_unmap(xs->data, xs->datalen, + ccb->data_nseg, ccb->data_phys); + } + aha_free_ccb(aha, ccb, xs->flags); + scsi_done(xs); + return COMPLETE; + } + if ((flags & SCSI_POLL) == 0) { timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000); splx(s); @@ -1402,19 +1428,18 @@ aha_set_bus_speed(aha) lastworking = speed; } if (lastworking == -1) { - printf("no working bus speed\n"); + printf(" no working bus speed"); return 0; } - printf("%d nsec ", aha_bus_speeds[lastworking].nsecs); + printf(", %d nsec ", aha_bus_speeds[lastworking].nsecs); if (lastworking == 7) /* is slowest already */ - printf("marginal\n"); + printf("marginal"); else { lastworking++; - printf("ok, using %d nsec\n", - aha_bus_speeds[lastworking].nsecs); + printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs); } if (!aha_bus_speed_check(aha, lastworking)) { - printf("test retry failed.. aborting.\n"); + printf("test retry failed.. aborting."); return 0; } return 1; @@ -1435,9 +1460,24 @@ aha_bus_speed_check(aha, speed) int speed; { int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed); - int loopcount; + int result, loopcount; + struct isadma_seg test_phys[1], scratch_phys[1]; u_char ad[3]; + result = 1; + + if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf), + scratch_phys, ISADMA_MAP_CONTIG) != 1) + return 0; + if (isadma_map(aha_test_string, sizeof(aha_test_string), + test_phys, ISADMA_MAP_CONTIG) != 1) { + isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); + return 0; + } + isadma_copytobuf(aha_test_string, sizeof(aha_test_string), + 1, test_phys); + /* * Set the dma-speed */ @@ -1448,7 +1488,7 @@ aha_bus_speed_check(aha, speed) * it's address. Read it onto the board */ for (loopcount = 100; loopcount; loopcount--) { - lto3b(KVTOPHYS(aha_test_string), ad); + lto3b(test_phys[0].addr, ad); aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]); /* @@ -1456,9 +1496,13 @@ aha_bus_speed_check(aha, speed) * board. */ bzero(aha_scratch_buf, 54); + isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); - lto3b(KVTOPHYS(aha_scratch_buf), ad); + lto3b(scratch_phys[0].addr, ad); aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]); + isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); /* * Compare the original data and the final data and return the @@ -1466,12 +1510,19 @@ aha_bus_speed_check(aha, speed) * first 54 bytes, because that's all the board copies during * WRITE_FIFO and READ_FIFO. */ - if (bcmp(aha_test_string, aha_scratch_buf, 54)) - return 0; /* failed test */ + if (bcmp(aha_test_string, aha_scratch_buf, 54)) { + result = 0; /* failed test */ + break; + } } + isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf), + 1, scratch_phys); + isadma_unmap(aha_test_string, sizeof(aha_test_string), + 1, test_phys); + /* copy succeeded; assume speed ok */ - return 1; + return result; } #endif /* TUNE_1542 */ diff --git a/sys/dev/isa/isadma.c b/sys/dev/isa/isadma.c index bcb72cc085b..cb353a57049 100644 --- a/sys/dev/isa/isadma.c +++ b/sys/dev/isa/isadma.c @@ -16,28 +16,31 @@ #include #include -/* region of physical memory known to be contiguous */ -vm_offset_t isaphysmem; -static caddr_t dma_bounce[8]; /* XXX */ -static char bounced[8]; /* XXX */ -#define MAXDMASZ 512 /* XXX */ +struct dma_info { + int flags; + caddr_t addr; + vm_size_t nbytes; + struct isadma_seg phys[1]; +}; + +static struct dma_info dma_info[8]; /* high byte of address is stored in this port for i-th dma channel */ static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; /* - * isa_dmacascade(): program 8237 DMA controller channel to accept + * isadma_cascade(): program 8237 DMA controller channel to accept * external dma control by a board. */ void -isa_dmacascade(chan) +isadma_cascade(chan) int chan; { #ifdef DIAGNOSTIC if (chan < 0 || chan > 7) - panic("isa_dmacascade: impossible request"); + panic("isadma_cascade: impossible request"); #endif /* set dma channel mode, and set dma channel mode */ @@ -51,43 +54,47 @@ isa_dmacascade(chan) } /* - * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment + * isadma_start(): program 8237 DMA controller channel, avoid page alignment * problems by using a bounce buffer. */ void -isa_dmastart(flags, addr, nbytes, chan) - int flags; +isadma_start(addr, nbytes, chan, flags) caddr_t addr; vm_size_t nbytes; int chan; + int flags; { - vm_offset_t phys; + struct dma_info *di; int waport; - caddr_t newaddr; + int mflags; + vm_size_t size; #ifdef DIAGNOSTIC if (chan < 0 || chan > 7 || + ((flags & ISADMA_START_READ) == 0) == ((flags & ISADMA_START_WRITE) == 0) || ((chan & 4) ? (nbytes >= (1<<17) || nbytes & 1 || (u_int)addr & 1) : (nbytes >= (1<<16)))) - panic("isa_dmastart: impossible request"); + panic("isadma_start: impossible request"); #endif - if (isa_dmarangecheck(addr, nbytes, chan)) { - if (dma_bounce[chan] == 0) - dma_bounce[chan] = - /*(caddr_t)malloc(MAXDMASZ, M_TEMP, M_WAITOK);*/ - (caddr_t) isaphysmem + NBPG*chan; - bounced[chan] = 1; - newaddr = dma_bounce[chan]; - *(int *) newaddr = 0; /* XXX */ - /* copy bounce buffer on write */ - if ((flags & B_READ) == 0) - bcopy(addr, newaddr, nbytes); - addr = newaddr; + di = dma_info+chan; + if (di->flags != 0) { + log(LOG_ERR,"isadma_start: old request active on %d\n",chan); + isadma_abort(chan); } - /* translate to physical */ - phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); + di->flags = flags; + di->addr = addr; + di->nbytes = nbytes; + + mflags = ISADMA_MAP_WAITOK | ISADMA_MAP_BOUNCE | ISADMA_MAP_CONTIG; + mflags |= (chan & 4) ? ISADMA_MAP_16BIT : ISADMA_MAP_8BIT; + + if (isadma_map(addr, nbytes, di->phys, mflags) != 1) + panic("isadma_start: cannot map"); + + if ((flags & ISADMA_START_READ) == 0) + isadma_copytobuf(addr, nbytes, 1, di->phys); if ((chan & 4) == 0) { /* @@ -95,7 +102,7 @@ isa_dmastart(flags, addr, nbytes, chan) * byte mode channels. */ /* set dma channel mode, and reset address ff */ - if (flags & B_READ) + if (flags & ISADMA_START_READ) outb(DMA1_MODE, chan | DMA37MD_SINGLE | DMA37MD_WRITE); else outb(DMA1_MODE, chan | DMA37MD_SINGLE | DMA37MD_READ); @@ -103,9 +110,9 @@ isa_dmastart(flags, addr, nbytes, chan) /* send start address */ waport = DMA1_CHN(chan); - outb(waport, phys); - outb(waport, phys>>8); - outb(dmapageport[chan], phys>>16); + outb(waport, di->phys[0].addr); + outb(waport, di->phys[0].addr>>8); + outb(dmapageport[chan], di->phys[0].addr>>16); /* send count */ outb(waport + 1, --nbytes); @@ -119,7 +126,7 @@ isa_dmastart(flags, addr, nbytes, chan) * word mode channels. */ /* set dma channel mode, and reset address ff */ - if (flags & B_READ) + if (flags & ISADMA_START_READ) outb(DMA2_MODE, (chan & 3) | DMA37MD_SINGLE | DMA37MD_WRITE); else outb(DMA2_MODE, (chan & 3) | DMA37MD_SINGLE | DMA37MD_READ); @@ -127,9 +134,9 @@ isa_dmastart(flags, addr, nbytes, chan) /* send start address */ waport = DMA2_CHN(chan & 3); - outb(waport, phys>>1); - outb(waport, phys>>9); - outb(dmapageport[chan], phys>>16); + outb(waport, di->phys[0].addr>>1); + outb(waport, di->phys[0].addr>>9); + outb(dmapageport[chan], di->phys[0].addr>>16); /* send count */ nbytes >>= 1; @@ -142,38 +149,50 @@ isa_dmastart(flags, addr, nbytes, chan) } void -isa_dmaabort(chan) +isadma_abort(chan) int chan; { + struct dma_info *di; #ifdef DIAGNOSTIC if (chan < 0 || chan > 7) - panic("isa_dmaabort: impossible request"); + panic("isadma_abort: impossible request"); #endif - bounced[chan] = 0; + di = dma_info+chan; + if (di->flags == 0) { + log(LOG_ERR,"isadma_abort: no request active on %d\n",chan); + return; + } /* mask channel */ if ((chan & 4) == 0) outb(DMA1_SMSK, DMA37SM_SET | chan); else outb(DMA2_SMSK, DMA37SM_SET | (chan & 3)); + + isadma_unmap(di->addr, di->nbytes, 1, di->phys); + di->flags = 0; } void -isa_dmadone(flags, addr, nbytes, chan) - int flags; - caddr_t addr; - vm_size_t nbytes; +isadma_done(chan) int chan; { + struct dma_info *di; u_char tc; #ifdef DIAGNOSTIC if (chan < 0 || chan > 7) - panic("isa_dmadone: impossible request"); + panic("isadma_done: impossible request"); #endif + di = dma_info+chan; + if (di->flags == 0) { + log(LOG_ERR,"isadma_done: no request active on %d\n",chan); + return; + } + /* check that the terminal count was reached */ if ((chan & 4) == 0) tc = inb(DMA1_SR) & (1 << chan); @@ -189,85 +208,9 @@ isa_dmadone(flags, addr, nbytes, chan) else outb(DMA2_SMSK, DMA37SM_SET | (chan & 3)); - /* copy bounce buffer on read */ - if (bounced[chan]) { - bcopy(dma_bounce[chan], addr, nbytes); - bounced[chan] = 0; - } -} + if (di->flags & ISADMA_START_READ) + isadma_copyfrombuf(di->addr, di->nbytes, 1, di->phys); -/* - * Check for problems with the address range of a DMA transfer - * (non-contiguous physical pages, outside of bus address space, - * crossing DMA page boundaries). - * Return true if special handling needed. - */ -int -isa_dmarangecheck(va, length, chan) - vm_offset_t va; - u_long length; - int chan; -{ - vm_offset_t phys, priorpage = 0, endva; - u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); - - endva = round_page(va + length); - for (; va < endva ; va += NBPG) { - phys = trunc_page(pmap_extract(pmap_kernel(), va)); - if (phys == 0) - panic("isa_dmacheck: no physical page present"); - if (phys >= (1<<24)) - return 1; - if (priorpage) { - if (priorpage + NBPG != phys) - return 1; - /* check if crossing a DMA page boundary */ - if ((priorpage ^ phys) & dma_pgmsk) - return 1; - } - priorpage = phys; - } - return 0; -} - -/* head of queue waiting for physmem to become available */ -struct buf isa_physmemq; - -/* blocked waiting for resource to become free for exclusive use */ -static isaphysmemflag; -/* if waited for and call requested when free (B_CALL) */ -static void (*isaphysmemunblock)(); /* needs to be a list */ - -/* - * Allocate contiguous physical memory for transfer, returning - * a *virtual* address to region. May block waiting for resource. - * (assumed to be called at splbio()) - */ -caddr_t -isa_allocphysmem(caddr_t va, unsigned length, void (*func)()) { - - isaphysmemunblock = func; - while (isaphysmemflag & B_BUSY) { - isaphysmemflag |= B_WANTED; - sleep((caddr_t)&isaphysmemflag, PRIBIO); - } - isaphysmemflag |= B_BUSY; - - return((caddr_t)isaphysmem); -} - -/* - * Free contiguous physical memory used for transfer. - * (assumed to be called at splbio()) - */ -void -isa_freephysmem(caddr_t va, unsigned length) { - - isaphysmemflag &= ~B_BUSY; - if (isaphysmemflag & B_WANTED) { - isaphysmemflag &= B_WANTED; - wakeup((caddr_t)&isaphysmemflag); - if (isaphysmemunblock) - (*isaphysmemunblock)(); - } + isadma_unmap(di->addr, di->nbytes, 1, di->phys); + di->flags = 0; } diff --git a/sys/dev/isa/isadmavar.h b/sys/dev/isa/isadmavar.h index e2c92c8e56d..d20a6e41e8f 100644 --- a/sys/dev/isa/isadmavar.h +++ b/sys/dev/isa/isadmavar.h @@ -1,6 +1,34 @@ /* $NetBSD: isadmavar.h,v 1.2 1994/10/27 04:17:09 cgd Exp $ */ -void isa_dmacascade __P((int)); -void isa_dmastart __P((int, caddr_t, vm_size_t, int)); -void isa_dmaabort __P((int)); -void isa_dmadone __P((int, caddr_t, vm_size_t, int)); +#define ISADMA_START_READ 0x0001 /* read from device */ +#define ISADMA_START_WRITE 0x0002 /* write to device */ + +#define ISADMA_MAP_WAITOK 0x0001 /* OK for isadma_map to sleep */ +#define ISADMA_MAP_BOUNCE 0x0002 /* use bounce buffer if necessary */ +#define ISADMA_MAP_CONTIG 0x0004 /* must be physically contiguous */ +#define ISADMA_MAP_8BIT 0x0008 /* must not cross 64k boundary */ +#define ISADMA_MAP_16BIT 0x0010 /* must not cross 128k boundary */ + +struct isadma_seg { /* a physical contiguous segment */ + vm_offset_t addr; /* address of this segment */ + vm_size_t length; /* length of this segment (bytes) */ +}; + +int isadma_map __P((caddr_t, vm_size_t, struct isadma_seg *, int)); +void isadma_unmap __P((caddr_t, vm_size_t, int, struct isadma_seg *)); +void isadma_copytobuf __P((caddr_t, vm_size_t, int, struct isadma_seg *)); +void isadma_copyfrombuf __P((caddr_t, vm_size_t, int, struct isadma_seg *)); + +void isadma_cascade __P((int)); +void isadma_start __P((caddr_t, vm_size_t, int, int)); +void isadma_abort __P((int)); +void isadma_done __P((int)); + +/* + * XXX these are needed until all drivers have been cleaned up + */ +#define isa_dmacascade(c) isadma_cascade((c)) +#define isa_dmastart(f, a, s, c) \ + isadma_start((a), (s), (c), (f)&B_READ?ISADMA_START_READ:ISADMA_START_WRITE) +#define isa_dmaabort(c) isadma_abort((c)) +#define isa_dmadone(a, s, c, f) isadma_abort((c)) diff --git a/sys/dev/isa/ultra14f.c b/sys/dev/isa/ultra14f.c index 4a2cf6255d3..849d486bc6d 100644 --- a/sys/dev/isa/ultra14f.c +++ b/sys/dev/isa/ultra14f.c @@ -66,6 +66,7 @@ #include #include +#include #include #include diff --git a/sys/dev/isa/wd.c b/sys/dev/isa/wd.c index 90b6f37f56f..c9d169560f2 100644 --- a/sys/dev/isa/wd.c +++ b/sys/dev/isa/wd.c @@ -55,6 +55,7 @@ #include #include +#include #include #define WAITTIME (4 * hz) /* time to wait for a completion */ diff --git a/sys/dev/isa/wd7000.c b/sys/dev/isa/wd7000.c index 97c1ebd1c25..cd86dd0e8ef 100644 --- a/sys/dev/isa/wd7000.c +++ b/sys/dev/isa/wd7000.c @@ -40,6 +40,7 @@ #include #include +#include #include /* XXX BROKEN */ extern int delaycount; /* from clock setup code */