From 906db1e92089cf4deabda49415a17e93e37624c5 Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 25 Oct 1998 17:26:41 +0000 Subject: [PATCH] PR/6274: John Ruschmeyer: Add support for the ncr53c80 driver on the i386. --- sys/dev/ic/README.ncr5380sbc | 186 ++++++++++++++++++++++++++++++ sys/dev/ic/ncr5380sbc.c | 211 ++++++++++++++++++----------------- sys/dev/ic/ncr5380var.h | 53 ++++++++- 3 files changed, 342 insertions(+), 108 deletions(-) create mode 100644 sys/dev/ic/README.ncr5380sbc diff --git a/sys/dev/ic/README.ncr5380sbc b/sys/dev/ic/README.ncr5380sbc new file mode 100644 index 000000000000..0022877b027e --- /dev/null +++ b/sys/dev/ic/README.ncr5380sbc @@ -0,0 +1,186 @@ +NCR 53C80/53C400 driver + +BACKGROUND +---------- +The NCR 53C80 SCSI Bus Controller (SBC) is an early single-chip solution +which formed the basis of many early SCSI host adapters for both the +i386 and m68k platforms. The NCR 53C400 is a slightly more advanced +chip which retains backward compatability with the 53C80. + +On the PC, the NCR 53C80 was most commonly used to implement simple, cheap +SCSI host adapters that were bundled with tape and CD-ROM drives. Since +these controllers were not bus-mastering (and in some cases were not even +interrupt-driven), they (like IDE adapters) required the CPU to perform +much of the actual processing. These days, these controllers are cheap +and plentiful since many are not supported by Windows 95. + +Similarly, NetBSD, although it has had an MI 53C80 driver (used by the +Sun3 and Mac68k ports) for some time, has not had a i386 driver. + +Until now, that is... + +OVERVIEW +-------- +The NCR 53C80/53C400 driver (the 'nca' device) consists of two pieces: + + 1) Patches for the 53C80 MI driver to make it use bus_space() + functions. (This requires an optional define. By default, + the driver will compile in "legacy" memory-mapped mode. + + 2) A machine-dependent driver (nca) containing probe and + attachment routines. + +This driver has bene tested with the following adapters: + + NCS-250 (Chinon) 53C80, port-mapped, polled-mode + (This is used in my primary development + box to drive an external Zip drive.) + Sumo SCSI-AT 53C80, port-mapped, interrupt driven + (Note: This is an odd card in that its + own firmware seems to have trouble detecting + attached drives. Under NetBSD, however, + it operates with no problems.) + Trantor T-160 53C400, port-mapped, interrupt driven + This card was often bundled with NEC + CD-ROM drives. (My standalone test box + is using this as its primary adapter.) + DTC 3150V 53C400, memory-mapped, interrupt driven + This a simple card designed to drive + a CD-ROM. + +CONFIGURATION +------------- +To setup the nca driver, the configuration file must contain the following: + + options NCR5380_USE_BUS_SPACE + +This line is required to add bus_space() compatability to the MI driver. + +Next you need to add one or more configuration lines for the nca devices: + + nca0 at isa? port 0x360 irq 15 + nca1 at isa? iomem 0xd8000 irq 5 + +The first is for a port-mapped controller at 0x360, IRQ 15. The second line +is for a memory-mapped controller (Trantor T128 or equivalent) at +0xd800-0xdff, IRQ 5. + +You can also set up the driver in "polled" mode (i.e., no interrupts) by +leaving off the "irq" portion of the line: + + nca0 at isa? port 0x360 + nca1 at isa? iomem 0xd8000 + +Lastly, you need to add a scsibus attachment line for the nca device: + + scsibus* at nca? + +The following is the probe output from my test system: + + Copyright (c) 1996, 1997, 1998 + The NetBSD Foundation, Inc. All rights reserved. + Copyright (c) 1982, 1986, 1989, 1991, 1993 + The Regents of the University of California. All rights reserved. + + NetBSD 1.3.2 (GENERIC) #2: Sun Oct 4 17:11:43 EDT 1998 + root@hefalump:/usr/src/sys/arch/i386/compile/GENERIC + cpu0: Intel 486DX (486-class) + real mem = 7995392 + avail mem = 5349376 + using 123 buffers containing 503808 bytes of memory + mainbus0 (root) + isa0 at mainbus0 + com1 at isa0 port 0x2f8-0x2ff irq 3: ns8250 or ns16450, no fifo + com2 at isa0 port 0x3e8-0x3ef irq 5: ns8250 or ns16450, no fifo + lpt0 at isa0 port 0x378-0x37b irq 7 + nca0 at isa0 port 0x360-0x36f irq 15 + nca0: NCR 53C400 detected + scsibus0 at nca0: 8 targets + sd0 at scsibus0 targ 0 lun 0: SCSI2 0/direct fixed + sd0: 402MB, 1574 cyl, 9 head, 58 sec, 512 bytes/sect x 825012 sectors + cd0 at scsibus0 targ 6 lun 0: SCSI2 5/cdrom removable + nca1 at isa0 iomem 0xdb878-0xdb887 irq 5 + nca1: NCR 53C400 detected + scsibus1 at nca1: 8 targets + sd1 at scsibus1 targ 5 lun 0: SCSI2 0/direct removable + sd1: 96MB, 96 cyl, 64 head, 32 sec, 512 bytes/sect x 196608 sectors + npx0 at isa0 port 0xf0-0xff: using exception 16 + pc0 at isa0 port 0x60-0x6f irq 1: color + pc0: console + fdc0 at isa0 port 0x3f0-0x3f7 irq 6 drq 2 + fd0 at fdc0 drive 0: 1.44MB, 80 cyl, 2 head, 18 sec + biomask 8060 netmask 8460 ttymask 84e2 + boot device: sd0 + root on sd0a dumps on sd0b + root file system type: ffs + +In this output, nca0 is a Trantor T-160 and nca1 is a DTC 3150V. Both happen +to be 53C400-based controllers. + +LIMITATIONS +----------- +As of this writing, the nca driver has two known limitations: + +1) No DMA or pseudo-DMA support + +This is unfortunate, but may be remedied in a later release. I would welcome +any help by someone more familiar with DMA, particularly in relation to +bus_space(). + +As it is, however, performance of the nca driver is acceptable, though some +of that may depend on one's definition of "acceptable". Remember that these +were not high speed controller under the best conditions, so much of it is +really the nature of the beast. It should be adequate for tapes, CD-ROMS, +and low-usage disk devices (e.g., Zip drives). If you want to drive a CD-R +drive, then invest in an Adaptec 154X or a PCI controller. + +2) No support for the SCSI port of the Pro AudioStudio 16. + +This is also unfortunate and may not be able to be remedied withing the +current framework of the bus_space() functions and the nca driver. + +The problem is this: In most adapters, the eight 53C80 registers are mapped +to eight sequential locations, either ports or memory addresses. On the +PAS-16, however, the registers are mapped to two sets of ports- four +sequential ports at the base address and four sequential ports located +0x2000 higher. As I currently understand it, this is not supportable by +the current bus_space() implementation nor is it possible for the driver +to allocate a second bus_space_tag and _handle itself to accomodate the +second set of ports. Without either, it is very difficult to imagine how +a portable linkage to the MI driver could be made. + +Again, I welcome suggestions. + +HISTORY +------- +An nca driver first appeared in FreeBSD. + +This particular one borrows a little code from it and some from the i386 +'esp' and sun3 'si' drivers. It, like many things in the free unix world, +was written because it solved a problem- mine! In my case, it was a need +of a SCSI card and a lack of IRQs. The good news was that I had one +(NCS-250); the bad news was that it was not supported under NetBSD. The +rest is history. + +DISCLAIMER +---------- +Like most things, you should take this code with a grain of salt. I have +tried to test it sufficiently, but it is always possible that it is not +compatible with some aspect of your system. If you end up suffering +massive data loss and destruction, you have my sympathies, but I do not +and will not allow myself to be held responsible. + +CREDITS +------- +My thanks to Jason Thorpe and the rest of the NetBSD team for making it +so easy to write this driver. My thanks also to the authors of the +FreeBSD nca driver for inspiration and 53C400 support. + +In the end, I hope that someone else can find this driver as useful as I +have. If so, please drop me a line at jruschme@exit109.com and let me +know about it. + +Share and enjoy + +John Ruschmeyer (jruschme@exit109.com) +11 October 1998 diff --git a/sys/dev/ic/ncr5380sbc.c b/sys/dev/ic/ncr5380sbc.c index 9f37e388dbbf..754154a41e21 100644 --- a/sys/dev/ic/ncr5380sbc.c +++ b/sys/dev/ic/ncr5380sbc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ncr5380sbc.c,v 1.27 1998/09/16 05:36:35 scottr Exp $ */ +/* $NetBSD: ncr5380sbc.c,v 1.28 1998/10/25 17:26:41 christos Exp $ */ /* * Copyright (c) 1995 David Jones, Gordon W. Ross @@ -64,6 +64,10 @@ * Michael L. Hitch (amiga drivers: sci.c) * Leo Weppelman (atari driver: ncr5380.c) * There are others too. Thanks, everyone. + * + * Transliteration to bus_space() performed 9/17/98 by + * John Ruschmeyer (jruschme@exit109.com) for i386 'nca' driver. + * Thank you all. */ #include "opt_ddb.h" @@ -186,7 +190,7 @@ static __inline int ncr5380_wait_req(sc) { register int timo = ncr5380_wait_req_timo; for (;;) { - if (*sc->sci_bus_csr & SCI_BUS_REQ) { + if (NCR5380_READ(sci_bus_csr) & SCI_BUS_REQ) { timo = 0; /* return 0 */ break; } @@ -203,7 +207,7 @@ static __inline int ncr5380_wait_not_req(sc) { register int timo = ncr5380_wait_nrq_timo; for (;;) { - if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) { + if ((NCR5380_READ(sci_bus_csr) & SCI_BUS_REQ) == 0) { timo = 0; /* return 0 */ break; } @@ -223,8 +227,8 @@ ncr_sched_msgout(sc, msg_code) /* First time, raise ATN line. */ if (sc->sc_msgpriq == 0) { register u_char icmd; - icmd = *sc->sci_icmd & SCI_ICMD_RMASK; - *sc->sci_icmd = icmd | SCI_ICMD_ATN; + icmd = NCR5380_READ(sci_icmd) & SCI_ICMD_RMASK; + NCR5380_WRITE(sci_icmd,icmd|SCI_ICMD_ATN); delay(2); } sc->sc_msgpriq |= msg_code; @@ -241,10 +245,10 @@ ncr5380_pio_out(sc, phase, count, data) register int resid; register int error; - icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK; + icmd = NCR5380_READ(sci_icmd) & SCI_ICMD_RMASK; icmd |= SCI_ICMD_DATA; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); resid = count; while (resid > 0) { @@ -256,25 +260,25 @@ ncr5380_pio_out(sc, phase, count, data) NCR_TRACE("pio_out: no REQ, resid=%d\n", resid); break; } - if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase) + if (SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)) != phase) break; /* Put the data on the bus. */ if (data) - *sc->sci_odata = *data++; + NCR5380_WRITE(sci_odata,*data++); else - *sc->sci_odata = 0; + NCR5380_WRITE(sci_odata,0); /* Tell the target it's there. */ icmd |= SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* Wait for target to get it. */ error = ncr5380_wait_not_req(sc); /* OK, it's got it (or we gave up waiting). */ icmd &= ~SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (error) { NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid); @@ -286,7 +290,7 @@ ncr5380_pio_out(sc, phase, count, data) /* Stop driving the data bus. */ icmd &= ~SCI_ICMD_DATA; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); return (count - resid); } @@ -302,7 +306,7 @@ ncr5380_pio_in(sc, phase, count, data) register int resid; register int error; - icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK; + icmd = NCR5380_READ(sci_icmd) & SCI_ICMD_RMASK; resid = count; while (resid > 0) { @@ -315,25 +319,25 @@ ncr5380_pio_in(sc, phase, count, data) break; } /* A phase change is not valid until AFTER REQ rises! */ - if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase) + if (SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)) != phase) break; /* Read the data bus. */ if (data) - *data++ = *sc->sci_data; + *data++ = NCR5380_READ(sci_data); else - (void) *sc->sci_data; + (void) NCR5380_READ(sci_data); /* Tell target we got it. */ icmd |= SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* Wait for target to drop REQ... */ error = ncr5380_wait_not_req(sc); /* OK, we can drop ACK. */ icmd &= ~SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (error) { NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid); @@ -369,14 +373,14 @@ ncr5380_init(sc) sc->sc_prevphase = PHASE_INVALID; sc->sc_state = NCR_IDLE; - *sc->sci_tcmd = PHASE_INVALID; - *sc->sci_icmd = 0; - *sc->sci_mode = 0; - *sc->sci_sel_enb = 0; + NCR5380_WRITE(sci_tcmd,PHASE_INVALID); + NCR5380_WRITE(sci_icmd,0); + NCR5380_WRITE(sci_mode,0); + NCR5380_WRITE(sci_sel_enb,0); SCI_CLR_INTR(sc); /* XXX: Enable reselect interrupts... */ - *sc->sci_sel_enb = 0x80; + NCR5380_WRITE(sci_sel_enb,0x80); /* Another hack (Er.. hook!) for the sun3 si: */ if (sc->sc_intr_on) { @@ -394,12 +398,12 @@ ncr5380_reset_scsibus(sc) NCR_TRACE("reset_scsibus, cur=0x%x\n", (long) sc->sc_current); - *sc->sci_icmd = SCI_ICMD_RST; + NCR5380_WRITE(sci_icmd,SCI_ICMD_RST); delay(500); - *sc->sci_icmd = 0; + NCR5380_WRITE(sci_icmd,0); - *sc->sci_mode = 0; - *sc->sci_tcmd = PHASE_INVALID; + NCR5380_WRITE(sci_mode,0); + NCR5380_WRITE(sci_tcmd,PHASE_INVALID); SCI_CLR_INTR(sc); /* XXX - Need long delay here! */ @@ -1084,7 +1088,7 @@ ncr5380_reselect(sc) * First, check the select line. * (That has to be set first.) */ - bus = *(sc->sci_bus_csr); + bus = NCR5380_READ(sci_bus_csr); if ((bus & SCI_BUS_SEL) == 0) { /* Not a selection or reselection. */ return; @@ -1111,7 +1115,7 @@ ncr5380_reselect(sc) return; } delay(2); - bus = *(sc->sci_bus_csr); + bus = NCR5380_READ(sci_bus_csr); /* If SEL went away, forget it. */ if ((bus & SCI_BUS_SEL) == 0) return; @@ -1125,7 +1129,7 @@ ncr5380_reselect(sc) * "bus settle delay" before we sample the data bus */ delay(2); - data = *(sc->sci_data) & 0xFF; + data = NCR5380_READ(sci_data) & 0xFF; /* Parity check is implicit in data validation below. */ /* @@ -1159,12 +1163,12 @@ ncr5380_reselect(sc) NCR_TRACE("reselect: target=0x%x\n", target); /* Raise BSY to acknowledge target reselection. */ - *(sc->sci_icmd) = SCI_ICMD_BSY; + NCR5380_WRITE(sci_icmd,SCI_ICMD_BSY); /* Wait for target to drop SEL. */ timo = ncr5380_wait_nrq_timo; for (;;) { - bus = *(sc->sci_bus_csr); + bus = NCR5380_READ(sci_bus_csr); if ((bus & SCI_BUS_SEL) == 0) break; /* success */ if (--timo <= 0) { @@ -1178,8 +1182,8 @@ ncr5380_reselect(sc) } /* Now we drop BSY, and we are connected. */ - *(sc->sci_icmd) = 0; - *sc->sci_sel_enb = 0; + NCR5380_WRITE(sci_icmd,0); + NCR5380_WRITE(sci_sel_enb,0); SCI_CLR_INTR(sc); /* @@ -1195,7 +1199,7 @@ ncr5380_reselect(sc) /* Try to send an ABORT message. */ goto abort; } - phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + phase = SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)); if (phase != PHASE_MSG_IN) { printf("%s: reselect, phase=%d\n", sc->sc_dev.dv_xname, phase); @@ -1203,10 +1207,10 @@ ncr5380_reselect(sc) } /* Ack. the change to PHASE_MSG_IN */ - *(sc->sci_tcmd) = PHASE_MSG_IN; + NCR5380_WRITE(sci_tcmd,PHASE_MSG_IN); /* Peek at the message byte without consuming it! */ - msg = *(sc->sci_data); + msg = NCR5380_READ(sci_data); if ((msg & 0x80) == 0) { printf("%s: reselect, not identify, msg=%d\n", sc->sc_dev.dv_xname, msg); @@ -1234,9 +1238,9 @@ ncr5380_reselect(sc) /* XXX: Restore the normal mode register. */ /* If this target's bit is set, do NOT check parity. */ if (sc->sc_parity_disable & target_mask) - *sc->sci_mode = (SCI_MODE_MONBSY); + NCR5380_WRITE(sci_mode,SCI_MODE_MONBSY); else - *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK); + NCR5380_WRITE(sci_mode,(SCI_MODE_MONBSY | SCI_MODE_PAR_CHK)); /* * Another hack for the Sun3 "si", which needs @@ -1265,7 +1269,7 @@ abort: /* Raise ATN, delay, raise ACK... */ icmd = SCI_ICMD_ATN; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); delay(2); /* Now consume the IDENTIFY message. */ @@ -1276,10 +1280,10 @@ abort: sc->sc_msgpriq = SEND_ABORT; ncr5380_msg_out(sc); - *(sc->sci_tcmd) = PHASE_INVALID; - *sc->sci_sel_enb = 0; + NCR5380_WRITE(sci_tcmd,PHASE_INVALID); + NCR5380_WRITE(sci_sel_enb,0); SCI_CLR_INTR(sc); - *sc->sci_sel_enb = 0x80; + NCR5380_WRITE(sci_sel_enb,0x80); sc->sc_state &= ~NCR_ABORTING; } @@ -1315,9 +1319,10 @@ ncr5380_select(sc, sr) * Set phase bits to 0, otherwise the 5380 won't drive the bus during * selection. */ - *sc->sci_tcmd = PHASE_DATA_OUT; - *sc->sci_icmd = icmd = 0; - *sc->sci_mode = 0; + NCR5380_WRITE(sci_tcmd,PHASE_DATA_OUT); + NCR5380_WRITE(sci_icmd,0); + icmd = 0; + NCR5380_WRITE(sci_mode,0); /* * Arbitrate for the bus. The 5380 takes care of the @@ -1338,14 +1343,14 @@ ncr5380_select(sc, sr) */ s = splimp(); /* XXX: Begin time-critical section */ - *(sc->sci_odata) = 0x80; /* OUR_ID */ - *(sc->sci_mode) = SCI_MODE_ARB; + NCR5380_WRITE(sci_odata,0x80); /* OUR_ID */ + NCR5380_WRITE(sci_mode,SCI_MODE_ARB); #define WAIT_AIP_USEC 20 /* pleanty of time */ /* Wait for the AIP bit to turn on. */ timo = WAIT_AIP_USEC; for (;;) { - if (*(sc->sci_icmd) & SCI_ICMD_AIP) + if (NCR5380_READ(sci_icmd) & SCI_ICMD_AIP) break; if (timo <= 0) { /* @@ -1366,7 +1371,7 @@ ncr5380_select(sc, sr) delay(3); /* Check for ICMD_LST */ - if (*(sc->sci_icmd) & SCI_ICMD_LST) { + if (NCR5380_READ(sci_icmd) & SCI_ICMD_LST) { /* Some other target asserted SEL. */ NCR_TRACE("select: lost one, rc=%d\n", XS_BUSY); goto lost_arb; @@ -1383,7 +1388,7 @@ ncr5380_select(sc, sr) * BSY directly so we can turn off ARB mode. */ icmd = (SCI_ICMD_BSY | SCI_ICMD_SEL); - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* * "The SCSI device that wins arbitration shall wait @@ -1399,13 +1404,13 @@ ncr5380_select(sc, sr) * there can be a higher selection ID than ours. * Keep this code for reference anyway... */ - if (*(sc->sci_icmd) & SCI_ICMD_LST) { + if (NCR5380_READ(sci_icmd) & SCI_ICMD_LST) { /* Some other target asserted SEL. */ NCR_TRACE("select: lost two, rc=%d\n", XS_BUSY); lost_arb: - *sc->sci_icmd = 0; - *sc->sci_mode = 0; + NCR5380_WRITE(sci_icmd,0); + NCR5380_WRITE(sci_mode,0); splx(s); /* XXX: End of time-critical section. */ @@ -1418,8 +1423,8 @@ ncr5380_select(sc, sr) } /* Leave ARB mode Now that we drive BSY+SEL */ - *sc->sci_mode = 0; - *sc->sci_sel_enb = 0; + NCR5380_WRITE(sci_mode,0); + NCR5380_WRITE(sci_sel_enb,0); splx(s); /* XXX: End of time-critical section. */ @@ -1431,14 +1436,14 @@ ncr5380_select(sc, sr) */ target_mask = (1 << sr->sr_target); data = 0x80 | target_mask; - *(sc->sci_odata) = data; + NCR5380_WRITE(sci_odata,data); icmd |= (SCI_ICMD_DATA | SCI_ICMD_ATN); - *(sc->sci_icmd) = icmd; + NCR5380_WRITE(sci_icmd,icmd); delay(2); /* two deskew delays. */ /* De-assert BSY (targets sample the data now). */ icmd &= ~SCI_ICMD_BSY; - *(sc->sci_icmd) = icmd; + NCR5380_WRITE(sci_icmd,icmd); delay(3); /* Bus settle delay. */ /* @@ -1446,7 +1451,7 @@ ncr5380_select(sc, sr) * SCSI spec. says wait for 250 mS. */ for (timo = 25000;;) { - if (*sc->sci_bus_csr & SCI_BUS_BSY) + if (NCR5380_READ(sci_bus_csr) & SCI_BUS_BSY) goto success; if (--timo <= 0) break; @@ -1462,16 +1467,16 @@ ncr5380_select(sc, sr) * otherwise we release the bus. */ icmd &= ~SCI_ICMD_DATA; - *(sc->sci_icmd) = icmd; + NCR5380_WRITE(sci_icmd,icmd); delay(201); - if ((*sc->sci_bus_csr & SCI_BUS_BSY) == 0) { + if ((NCR5380_READ(sci_bus_csr) & SCI_BUS_BSY) == 0) { /* Really no device on bus */ - *sc->sci_tcmd = PHASE_INVALID; - *sc->sci_icmd = 0; - *sc->sci_mode = 0; - *sc->sci_sel_enb = 0; + NCR5380_WRITE(sci_tcmd,PHASE_INVALID); + NCR5380_WRITE(sci_icmd,0); + NCR5380_WRITE(sci_mode,0); + NCR5380_WRITE(sci_sel_enb,0); SCI_CLR_INTR(sc); - *sc->sci_sel_enb = 0x80; + NCR5380_WRITE(sci_sel_enb,0x80); NCR_TRACE("select: device down, rc=%d\n", XS_SELTIMEOUT); return XS_SELTIMEOUT; } @@ -1483,13 +1488,13 @@ success: * Configure the ncr5380 to monitor BSY, parity. */ icmd &= ~(SCI_ICMD_DATA | SCI_ICMD_SEL); - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* If this target's bit is set, do NOT check parity. */ if (sc->sc_parity_disable & target_mask) - *sc->sci_mode = (SCI_MODE_MONBSY); + NCR5380_WRITE(sci_mode,SCI_MODE_MONBSY); else - *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK); + NCR5380_WRITE(sci_mode,(SCI_MODE_MONBSY | SCI_MODE_PAR_CHK)); return XS_NOERROR; } @@ -1549,10 +1554,10 @@ ncr5380_msg_in(sc) register u_char icmd; /* acknowledge phase change */ - *sc->sci_tcmd = PHASE_MSG_IN; + NCR5380_WRITE(sci_tcmd,PHASE_MSG_IN); act_flags = ACT_CONTINUE; - icmd = *sc->sci_icmd & SCI_ICMD_RMASK; + icmd = NCR5380_READ(sci_icmd) & SCI_ICMD_RMASK; if (sc->sc_prevphase == PHASE_MSG_IN) { /* This is a continuation of the previous message. */ @@ -1590,7 +1595,7 @@ nextbyte: /* Just let ncr5380_machine() handle it... */ return (act_flags); } - phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + phase = SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)); if (phase != PHASE_MSG_IN) { /* * Target left MESSAGE IN, probably because it @@ -1600,7 +1605,7 @@ nextbyte: return (act_flags); } /* Still in MESSAGE IN phase, and REQ is asserted. */ - if (*sc->sci_csr & SCI_CSR_PERR) { + if (NCR5380_READ(sci_csr) & SCI_CSR_PERR) { ncr_sched_msgout(sc, SEND_PARITY_ERROR); sc->sc_state |= NCR_DROP_MSGIN; } @@ -1611,7 +1616,7 @@ nextbyte: ncr_sched_msgout(sc, SEND_REJECT); sc->sc_state |= NCR_DROP_MSGIN; } else { - *sc->sc_imp++ = *sc->sci_data; + *sc->sc_imp++ = NCR5380_READ(sci_data); n++; /* * This testing is suboptimal, but most @@ -1637,7 +1642,7 @@ nextbyte: /* Ack the last byte read. */ icmd |= SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (ncr5380_wait_not_req(sc)) { NCR_TRACE("msg_in: drop, stuck REQ, n=%d\n", n); @@ -1645,7 +1650,7 @@ nextbyte: } icmd &= ~SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (act_flags != ACT_CONTINUE) return (act_flags); @@ -1738,7 +1743,7 @@ have_msg: /* Ack the last byte read. */ icmd |= SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (ncr5380_wait_not_req(sc)) { NCR_TRACE("msg_in: last, stuck REQ, n=%d\n", n); @@ -1746,7 +1751,7 @@ have_msg: } icmd &= ~SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* Go get the next message, if any. */ if (act_flags == ACT_CONTINUE) @@ -1784,7 +1789,7 @@ ncr5380_msg_out(sc) register u_char icmd, msg; /* acknowledge phase change */ - *sc->sci_tcmd = PHASE_MSG_OUT; + NCR5380_WRITE(sci_tcmd,PHASE_MSG_OUT); progress = 0; /* did we send any messages? */ act_flags = ACT_CONTINUE; @@ -1793,9 +1798,9 @@ ncr5380_msg_out(sc) * Set ATN. If we're just sending a trivial 1-byte message, * we'll clear ATN later on anyway. Also drive the data bus. */ - icmd = *sc->sci_icmd & SCI_ICMD_RMASK; + icmd = NCR5380_READ(sci_icmd) & SCI_ICMD_RMASK; icmd |= (SCI_ICMD_ATN | SCI_ICMD_DATA); - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (sc->sc_prevphase == PHASE_MSG_OUT) { if (sc->sc_omp == sc->sc_omess) { @@ -1922,7 +1927,7 @@ nextbyte: NCR_TRACE("msg_out: no REQ, n=%d\n", n); goto out; } - phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + phase = SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)); if (phase != PHASE_MSG_OUT) { /* * Target left MESSAGE OUT, possibly to reject @@ -1938,17 +1943,17 @@ nextbyte: /* Clear ATN before last byte if this is the last message. */ if (n == 0 && sc->sc_msgpriq == 0) { icmd &= ~SCI_ICMD_ATN; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* 2 deskew delays */ delay(2); /* XXX */ } /* Put data on the bus. */ - *sc->sci_odata = *--sc->sc_omp; + NCR5380_WRITE(sci_odata,*--sc->sc_omp); /* Raise ACK to tell target data is on the bus. */ icmd |= SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* Wait for REQ to be negated. */ if (ncr5380_wait_not_req(sc)) { @@ -1958,7 +1963,7 @@ nextbyte: /* Finally, drop ACK. */ icmd &= ~SCI_ICMD_ACK; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); /* Stuck bus or something... */ if (act_flags & ACT_RESET_BUS) @@ -1984,7 +1989,7 @@ nextbyte: out: /* Stop driving the data bus. */ icmd &= ~SCI_ICMD_DATA; - *sc->sci_icmd = icmd; + NCR5380_WRITE(sci_icmd,icmd); if (!progress) act_flags |= ACT_RESET_BUS; @@ -2006,7 +2011,7 @@ ncr5380_command(sc) int len; /* acknowledge phase change */ - *sc->sci_tcmd = PHASE_COMMAND; + NCR5380_WRITE(sci_tcmd,PHASE_COMMAND); if (sr->sr_flags & SR_SENSE) { rqs.opcode = REQUEST_SENSE; @@ -2063,7 +2068,7 @@ ncr5380_data_xfer(sc, phase) goto abort; } /* acknowledge phase change */ - *sc->sci_tcmd = PHASE_DATA_IN; + NCR5380_WRITE(sci_tcmd,PHASE_DATA_IN); len = ncr5380_pio_in(sc, phase, sizeof(xs->sense.scsi_sense), (u_char *)&xs->sense.scsi_sense); return ACT_CONTINUE; @@ -2094,7 +2099,7 @@ ncr5380_data_xfer(sc, phase) else ncr5380_pio_out(sc, phase, 4096, NULL); /* Make sure that caused a phase change. */ - if (SCI_BUS_PHASE(*sc->sci_bus_csr) == phase) { + if (SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)) == phase) { /* More than 4k is just too much! */ printf("%s: too much data padding\n", sc->sc_dev.dv_xname); @@ -2127,7 +2132,7 @@ ncr5380_data_xfer(sc, phase) */ NCR_TRACE("data_xfer: doing PIO, len=%d\n", sc->sc_datalen); /* acknowledge phase change */ - *sc->sci_tcmd = phase; /* XXX: OK for PDMA? */ + NCR5380_WRITE(sci_tcmd,phase); /* XXX: OK for PDMA? */ if (phase == PHASE_DATA_OUT) { len = (*sc->sc_pio_out)(sc, phase, sc->sc_datalen, sc->sc_dataptr); } else { @@ -2155,7 +2160,7 @@ ncr5380_status(sc) struct sci_req *sr = sc->sc_current; /* acknowledge phase change */ - *sc->sci_tcmd = PHASE_STATUS; + NCR5380_WRITE(sci_tcmd,PHASE_STATUS); len = ncr5380_pio_in(sc, PHASE_STATUS, 1, &status); if (len) { @@ -2223,7 +2228,7 @@ next_phase: */ timo = ncr5380_wait_phase_timo; for (;;) { - if (*sc->sci_bus_csr & SCI_BUS_REQ) + if (NCR5380_READ(sci_bus_csr) & SCI_BUS_REQ) break; if (--timo <= 0) { if (sc->sc_state & NCR_ABORTING) { @@ -2241,7 +2246,7 @@ next_phase: delay(100); } - phase = SCI_BUS_PHASE(*sc->sci_bus_csr); + phase = SCI_BUS_PHASE(NCR5380_READ(sci_bus_csr)); NCR_TRACE("machine: phase=%s\n", (long) phase_names[phase & 7]); @@ -2256,7 +2261,7 @@ next_phase: * XXX: ... each phase routine does that itself. * In particular, DMA needs it done LATER. */ - *sc->sci_tcmd = phase; /* acknowledge phase change */ + NCR5380_WRITE(sci_tcmd,phase); /* acknowledge phase change */ #endif switch (phase) { @@ -2327,7 +2332,7 @@ do_actions: * Check for parity error. * XXX - better place to check? */ - if (*(sc->sci_csr) & SCI_CSR_PERR) { + if (NCR5380_READ(sci_csr) & SCI_CSR_PERR) { printf("%s: parity error!\n", sc->sc_dev.dv_xname); /* XXX: sc->sc_state |= NCR_ABORTING; */ ncr_sched_msgout(sc, SEND_PARITY_ERROR); @@ -2389,12 +2394,12 @@ do_actions: NCR_TRACE("machine: discon, waited %d\n", ncr5380_wait_req_timo - timo); - *sc->sci_icmd = 0; - *sc->sci_mode = 0; - *sc->sci_tcmd = PHASE_INVALID; - *sc->sci_sel_enb = 0; + NCR5380_WRITE(sci_icmd,0); + NCR5380_WRITE(sci_mode,0); + NCR5380_WRITE(sci_tcmd,PHASE_INVALID); + NCR5380_WRITE(sci_sel_enb,0); SCI_CLR_INTR(sc); - *sc->sci_sel_enb = 0x80; + NCR5380_WRITE(sci_sel_enb,0x80); if ((act_flags & ACT_CMD_DONE) == 0) { __asm("_ncr5380_disconnected:"); diff --git a/sys/dev/ic/ncr5380var.h b/sys/dev/ic/ncr5380var.h index d0ccac4f72ed..a1ef7596814d 100644 --- a/sys/dev/ic/ncr5380var.h +++ b/sys/dev/ic/ncr5380var.h @@ -1,4 +1,4 @@ -/* $NetBSD: ncr5380var.h,v 1.8 1997/08/27 11:24:58 bouyer Exp $ */ +/* $NetBSD: ncr5380var.h,v 1.9 1998/10/25 17:26:41 christos Exp $ */ /* * Copyright (c) 1995 David Jones, Gordon W. Ross @@ -37,8 +37,35 @@ * module and the machine-indepenedent ncr5380sbc.c module. */ -#define SCI_CLR_INTR(sc) (*(sc)->sci_iack) -#define SCI_BUSY(sc) (*sc->sci_bus_csr & SCI_BUS_BSY) +/* + * Only the i386 uses real bus space: + * arm32: oak and csa drivers; easy to convert + * mac68k: sbc driver; easy to convert + * pc532: ncr driver; need bus.h first + * sparc: si and sw drivers; easy to convert + * sun3: si driver; need bus.h first + * vax: ncr driver; need bus.h first + */ +#ifdef __i386__ +# define NCR5380_USE_BUS_SPACE +#endif + +/* + * Handy read/write macros + */ +#if NCR5380_USE_BUS_SPACE +# include +/* bus_space() variety */ +# define NCR5380_READ(reg) bus_space_read_1(sc->iot,sc->ioh,sc->reg) +# define NCR5380_WRITE(reg,val) bus_space_write_1(sc->iot,sc->ioh,sc->reg,val) +#else +/* legacy memory-mapped variety */ +# define NCR5380_READ(reg) *sc->reg +# define NCR5380_WRITE(reg,val) *(sc->reg) = val +#endif + +#define SCI_CLR_INTR(sc) NCR5380_READ(sci_iack) +#define SCI_BUSY(sc) (NCR5380_READ(sci_bus_csr) & SCI_BUS_BSY) /* These are NOT artibtrary, but map to bits in sci_tcmd */ #define PHASE_DATA_OUT 0x0 @@ -76,9 +103,24 @@ struct sci_req { struct ncr5380_softc { - struct device sc_dev; - struct scsipi_link sc_link; + struct device sc_dev; + struct scsipi_link sc_link; +#ifdef NCR5380_USE_BUS_SPACE + /* Pointers to bus_space */ + bus_space_tag_t iot; + bus_space_handle_t ioh; + + /* Pointers to 5380 registers. */ + bus_size_t sci_r0; + bus_size_t sci_r1; + bus_size_t sci_r2; + bus_size_t sci_r3; + bus_size_t sci_r4; + bus_size_t sci_r5; + bus_size_t sci_r6; + bus_size_t sci_r7; +#else /* Pointers to 5380 registers. See ncr5380reg.h */ volatile u_char *sci_r0; volatile u_char *sci_r1; @@ -88,6 +130,7 @@ struct ncr5380_softc { volatile u_char *sci_r5; volatile u_char *sci_r6; volatile u_char *sci_r7; +#endif /* Functions set from MD code */ int (*sc_pio_out) __P((struct ncr5380_softc *,