diff --git a/sys/dev/aha/aha.c b/sys/dev/aha/aha.c index b213adc45e46..dcabdeaa71ad 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 #include #include @@ -79,10 +81,15 @@ #include #include + +#if NPNP > 0 +#include +#include /* XXX pnp isn't x86 only */ +#endif #include -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 f7183305baba..94266790e87f 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 #include +#include #include #include @@ -42,9 +45,13 @@ #include -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 +#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 48bb20caf6a9..82f3f4a49bd4 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 f7183305baba..94266790e87f 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 #include +#include #include #include @@ -42,9 +45,13 @@ #include -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 +#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