diff options
author | imp <imp@FreeBSD.org> | 1999-01-20 06:21:27 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 1999-01-20 06:21:27 +0000 |
commit | 00736ae9131bddd05cf204fdd53a52aaf79adf63 (patch) | |
tree | 4c9e30ee3ffad6a0847cf82407827b9e244d9e38 | |
parent | 0b91534f2d2280f6af9d8d1f3067a9540ea4ffcc (diff) | |
download | FreeBSD-src-00736ae9131bddd05cf204fdd53a52aaf79adf63.zip FreeBSD-src-00736ae9131bddd05cf204fdd53a52aaf79adf63.tar.gz |
o enable plug and play support for the aha driver. Given the cumbersome
pnp system in freebsd, I'm not sure how useful this will be, but my
1542CP seems to work well in plug and play mode and does seem to
probe correctly at all the oddball addresses/irq/drqs that I tried.
[[
I was unable to get /kernel.conf or /kernel.config to read in, so
I wasn't able to verify that this method of userconfig works. that's
one thing that makes pnp so hard to use in the current scheme.
Pointers to the right new way of doing this accepted.
]]
o Add some kludges to maybe bring support for 1540A/1542A into the
driver. Since I have no 154xA cards, and the only person I know
that has them hasn't given me feedback, I'm making this commit
blind.
o Honor unit numbers that are in the config file now. This allows one
to hard wire the unit numbers (and have high unit numbers for plug
and pray devices, which can't seem to be hardwired) and have the
cards not migrate from aha1 -> aha0 should aha0 go on the fritz. I
didn't verify that hard wired scsi busses would work, but did verify
that hard wired aha addresses did work to a limited extent. Both
aha0 and aha1 must be hardwired, or when the card that was in aha0
goes away, the probe for aha0 might pick up the card that otherwise
would have been aha1.
-rw-r--r-- | sys/dev/aha/aha.c | 39 | ||||
-rw-r--r-- | sys/dev/aha/aha_isa.c | 99 | ||||
-rw-r--r-- | sys/dev/aha/ahareg.h | 18 | ||||
-rw-r--r-- | sys/i386/isa/aha_isa.c | 99 |
4 files changed, 221 insertions, 34 deletions
diff --git a/sys/dev/aha/aha.c b/sys/dev/aha/aha.c index b213adc..dcabdea 100644 --- a/sys/dev/aha/aha.c +++ b/sys/dev/aha/aha.c @@ -55,9 +55,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha.c,v 1.17 1998/12/22 18:14:50 gibbs Exp $ + * $Id: aha.c,v 1.18 1998/12/22 22:31:06 imp Exp $ */ +#include "pnp.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> @@ -79,10 +81,15 @@ #include <vm/vm.h> #include <vm/pmap.h> + +#if NPNP > 0 +#include <i386/isa/isa_device.h> +#include <i386/isa/pnp.h> /* XXX pnp isn't x86 only */ +#endif #include <dev/aha/ahareg.h> -struct aha_softc *aha_softcs[NAHA]; +struct aha_softc *aha_softcs[NAHATOT]; #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define PRVERB(x) if (bootverbose) printf x @@ -209,7 +216,7 @@ aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh) struct aha_softc *aha; if (unit != AHA_TEMP_UNIT) { - if (unit >= NAHA) { + if (unit >= NAHATOT) { printf("aha: unit number (%d) too high\n", unit); return NULL; } @@ -235,6 +242,8 @@ aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh) aha->unit = unit; aha->tag = tag; aha->bsh = bsh; + aha->ccb_sg_opcode = INITIATOR_SG_CCB_WRESID; + aha->ccb_ccb_opcode = INITIATOR_CCB_WRESID; if (aha->unit != AHA_TEMP_UNIT) { aha_softcs[unit] = aha; @@ -902,7 +911,7 @@ ahaaction(struct cam_sim *sim, union ccb *ccb) csio = &ccb->csio; ccbh = &csio->ccb_h; - hccb->opcode = INITIATOR_CCB_WRESID; + hccb->opcode = aha->ccb_ccb_opcode; hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0; hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0; hccb->cmd_len = csio->cdb_len; @@ -1169,7 +1178,7 @@ ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) } if (nseg > 1) { - accb->hccb.opcode = INITIATOR_SG_CCB_WRESID; + accb->hccb.opcode = aha->ccb_sg_opcode; ahautoa24((sizeof(aha_sg_t) * nseg), accb->hccb.data_len); ahautoa24(accb->sg_list_phys, accb->hccb.data_addr); @@ -1360,7 +1369,10 @@ ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_co case AMBI_ABORT: case AMBI_ERROR: /* An error occured */ - csio->resid = aha_a24tou(accb->hccb.data_len); + if (accb->hccb.opcode < INITIATOR_CCB_WRESID) + csio->resid = 0; + else + csio->resid = aha_a24tou(accb->hccb.data_len); switch(accb->hccb.ahastat) { case AHASTAT_DATARUN_ERROR: { @@ -1406,8 +1418,16 @@ ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_co panic("%s: Inavlid Action code", aha_name(aha)); break; case AHASTAT_INVALID_OPCODE: - panic("%s: Invalid CCB Opcode code %x hccb = %p", - aha_name(aha), accb->hccb.opcode, &accb->hccb); + if (accb->hccb.opcode < INITIATOR_CCB_WRESID) + panic("%s: Invalid CCB Opcode %x hccb = %p", + aha_name(aha), accb->hccb.opcode, + &accb->hccb); + printf("%s: AHA-1540A detected, compensating\n", + aha_name(aha)); + aha->ccb_sg_opcode = INITIATOR_SG_CCB; + aha->ccb_ccb_opcode = INITIATOR_CCB; + xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); + csio->ccb_h.status = CAM_REQUEUE_REQ; break; case AHASTAT_LINKED_CCB_LUN_MISMATCH: /* We don't even support linked commands... */ @@ -1418,7 +1438,7 @@ ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_co break; case AHASTAT_HA_SCSI_BUS_RESET: if ((csio->ccb_h.status & CAM_STATUS_MASK) - != CAM_CMD_TIMEOUT) + != CAM_CMD_TIMEOUT) csio->ccb_h.status = CAM_SCSI_BUS_RESET; break; case AHASTAT_HA_BDR: @@ -1440,6 +1460,7 @@ ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_co case AMBI_OK: /* All completed without incident */ /* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */ + /* I don't think so since it works???? */ ccb->ccb_h.status |= CAM_REQ_CMP; if ((accb->flags & ACCB_RELEASE_SIMQ) != 0) ccb->ccb_h.status |= CAM_RELEASE_SIMQ; diff --git a/sys/dev/aha/aha_isa.c b/sys/dev/aha/aha_isa.c index f718330..9426679 100644 --- a/sys/dev/aha/aha_isa.c +++ b/sys/dev/aha/aha_isa.c @@ -28,11 +28,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha_isa.c,v 1.4 1998/10/12 18:53:33 imp Exp $ + * $Id: aha_isa.c,v 1.5 1998/11/10 06:44:54 gibbs Exp $ */ +#include "pnp.h" + #include <sys/param.h> #include <sys/systm.h> +#include <sys/kernel.h> #include <machine/bus_pio.h> #include <machine/bus.h> @@ -42,9 +45,13 @@ #include <cam/scsi/scsi_all.h> -static int aha_isa_probe __P((struct isa_device *dev)); -static int aha_isa_attach __P((struct isa_device *dev)); -static void aha_isa_intr __P((void *unit)); +#if NPNP > 0 +#include <i386/isa/pnp.h> +#endif + +static int aha_isa_probe(struct isa_device *dev); +static int aha_isa_attach(struct isa_device *dev); +static void aha_isa_intr(void *unit); struct isa_driver ahadriver = { @@ -70,14 +77,6 @@ aha_isa_probe(dev) int port_index; int max_port_index; - /* - * We ignore the unit number assigned by config to allow - * consistant numbering between PCI/EISA/ISA devices. - * This is a total kludge until we have a configuration - * manager. - */ - dev->id_unit = aha_unit; - aha = NULL; /* @@ -214,3 +213,79 @@ aha_isa_intr(void *unit) struct aha_softc* arg = aha_softcs[(int)unit]; aha_intr((void *)arg); } + +/* + * support PnP cards if we are using 'em + */ + +#if NPNP > 0 + +static char *ahapnp_probe(u_long csn, u_long vend_id); +static void ahapnp_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev); +static u_long nahapnp = NAHA; + +static struct pnp_device ahapnp = { + "ahapnp", + ahapnp_probe, + ahapnp_attach, + &nahapnp, + &bio_imask +}; +DATA_SET (pnpdevice_set, ahapnp); + +static char * +ahapnp_probe(u_long csn, u_long vend_id) +{ + struct pnp_cinfo d; + char *s = NULL; + + if (vend_id != AHA1542_PNP && vend_id != AHA1542_PNPCOMPAT) + return (NULL); + + read_pnp_parms(&d, 0); + if (d.enable == 0 || d.flags & 1) { + printf("CSN %lu is disabled.\n", csn); + return (NULL); + } + s = "Adaptec 1542CP"; + + return (s); +} + +static void +ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) +{ + struct pnp_cinfo d; + struct isa_device *dvp; + + if (dev->id_unit >= NAHATOT) + return; + + if (read_pnp_parms(&d, 0) == 0) { + printf("failed to read pnp parms\n"); + return; + } + + write_pnp_parms(&d, 0); + + enable_pnp_card(); + + dev->id_iobase = d.port[0]; + dev->id_irq = (1 << d.irq[0]); + dev->id_intr = aha_intr; + dev->id_drq = d.drq[0]; + + if (dev->id_driver == NULL) { + dev->id_driver = &ahadriver; + dvp = find_isadev(isa_devtab_tty, &ahadriver, 0); + if (dvp != NULL) + dev->id_id = dvp->id_id; + } + + if ((dev->id_alive = aha_isa_probe(dev)) != 0) + aha_isa_attach(dev); + else + printf("aha%d: probe failed\n", dev->id_unit); +} +#endif diff --git a/sys/dev/aha/ahareg.h b/sys/dev/aha/ahareg.h index 48bb20c..82f3f4a 100644 --- a/sys/dev/aha/ahareg.h +++ b/sys/dev/aha/ahareg.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ahareg.h,v 1.3 1998/10/02 04:37:49 imp Exp $ + * $Id: ahareg.h,v 1.4 1998/11/10 06:44:42 gibbs Exp $ */ #ifndef _AHAREG_H_ @@ -349,6 +349,8 @@ struct aha_softc { LIST_HEAD(,ccb_hdr) pending_ccbs; u_int active_ccbs; u_int32_t aha_ccb_physbase; + aha_ccb_opcode_t ccb_sg_opcode; + aha_ccb_opcode_t ccb_ccb_opcode; aha_mbox_in_t *in_boxes; aha_mbox_out_t *out_boxes; struct scsi_sense_data *sense_buffers; @@ -428,4 +430,18 @@ int aha_cmd(struct aha_softc *aha, aha_op_t opcode, #define aha_outb(aha, port, value) \ bus_space_write_1((aha)->tag, (aha)->bsh, port, value) + +#ifndef EXTRA_AHA +#if NPNP > 0 +#define EXTRA_AHA MAX_PNP_CARDS +#else +#define EXTRA_AHA 0 +#endif +#endif + +#define NAHATOT (NAHA + EXTRA_AHA) + +#define AHA1542_PNP 0x42159004 /* ADP1542 */ +#define AHA1542_PNPCOMPAT 0xA000D040 /* PNP00A0 */ + #endif /* _AHA_H_ */ diff --git a/sys/i386/isa/aha_isa.c b/sys/i386/isa/aha_isa.c index f718330..9426679 100644 --- a/sys/i386/isa/aha_isa.c +++ b/sys/i386/isa/aha_isa.c @@ -28,11 +28,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha_isa.c,v 1.4 1998/10/12 18:53:33 imp Exp $ + * $Id: aha_isa.c,v 1.5 1998/11/10 06:44:54 gibbs Exp $ */ +#include "pnp.h" + #include <sys/param.h> #include <sys/systm.h> +#include <sys/kernel.h> #include <machine/bus_pio.h> #include <machine/bus.h> @@ -42,9 +45,13 @@ #include <cam/scsi/scsi_all.h> -static int aha_isa_probe __P((struct isa_device *dev)); -static int aha_isa_attach __P((struct isa_device *dev)); -static void aha_isa_intr __P((void *unit)); +#if NPNP > 0 +#include <i386/isa/pnp.h> +#endif + +static int aha_isa_probe(struct isa_device *dev); +static int aha_isa_attach(struct isa_device *dev); +static void aha_isa_intr(void *unit); struct isa_driver ahadriver = { @@ -70,14 +77,6 @@ aha_isa_probe(dev) int port_index; int max_port_index; - /* - * We ignore the unit number assigned by config to allow - * consistant numbering between PCI/EISA/ISA devices. - * This is a total kludge until we have a configuration - * manager. - */ - dev->id_unit = aha_unit; - aha = NULL; /* @@ -214,3 +213,79 @@ aha_isa_intr(void *unit) struct aha_softc* arg = aha_softcs[(int)unit]; aha_intr((void *)arg); } + +/* + * support PnP cards if we are using 'em + */ + +#if NPNP > 0 + +static char *ahapnp_probe(u_long csn, u_long vend_id); +static void ahapnp_attach(u_long csn, u_long vend_id, char *name, + struct isa_device *dev); +static u_long nahapnp = NAHA; + +static struct pnp_device ahapnp = { + "ahapnp", + ahapnp_probe, + ahapnp_attach, + &nahapnp, + &bio_imask +}; +DATA_SET (pnpdevice_set, ahapnp); + +static char * +ahapnp_probe(u_long csn, u_long vend_id) +{ + struct pnp_cinfo d; + char *s = NULL; + + if (vend_id != AHA1542_PNP && vend_id != AHA1542_PNPCOMPAT) + return (NULL); + + read_pnp_parms(&d, 0); + if (d.enable == 0 || d.flags & 1) { + printf("CSN %lu is disabled.\n", csn); + return (NULL); + } + s = "Adaptec 1542CP"; + + return (s); +} + +static void +ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) +{ + struct pnp_cinfo d; + struct isa_device *dvp; + + if (dev->id_unit >= NAHATOT) + return; + + if (read_pnp_parms(&d, 0) == 0) { + printf("failed to read pnp parms\n"); + return; + } + + write_pnp_parms(&d, 0); + + enable_pnp_card(); + + dev->id_iobase = d.port[0]; + dev->id_irq = (1 << d.irq[0]); + dev->id_intr = aha_intr; + dev->id_drq = d.drq[0]; + + if (dev->id_driver == NULL) { + dev->id_driver = &ahadriver; + dvp = find_isadev(isa_devtab_tty, &ahadriver, 0); + if (dvp != NULL) + dev->id_id = dvp->id_id; + } + + if ((dev->id_alive = aha_isa_probe(dev)) != 0) + aha_isa_attach(dev); + else + printf("aha%d: probe failed\n", dev->id_unit); +} +#endif |