+/* #define ML11 0 to remove ML11 support */
+#define ML11 (hptypes[mi->mi_type] == MBDT_ML11A)
+#define RP06 (hptypes[mi->mi_type] <= MBDT_RP06)
+#define RM80 (hptypes[mi->mi_type] == MBDT_RM80)
+
+#define hpunit(dev) (minor(dev) >> 3)
+#define MASKREG(reg) ((reg)&0xffff)
+#define HPWAIT(mi, addr) (((addr)->hpds & HPDS_DRY) || hpwait(mi))
+
+/*ARGSUSED*/
+hpattach(mi, slave)
+ register struct mba_device *mi;
+{
+
+ mi->mi_type = hpmaptype(mi);
+ if (!ML11 && mi->mi_dk >= 0) {
+ struct hpst *st = &hpst[mi->mi_type];
+
+ dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
+ }
+}
+
+/*
+ * Map apparent MASSBUS drive type into manufacturer
+ * specific configuration. For SI controllers this is done
+ * based on codes in the serial number register. For
+ * EMULEX controllers, the track and sector attributes are
+ * used when the drive type is an RM02 (not supported by DEC).
+ */
+hpmaptype(mi)
+ register struct mba_device *mi;
+{
+ register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
+ register int type = mi->mi_type;
+
+ /*
+ * Model-byte processing for SI controllers.
+ * NB: Only deals with RM03 and RM05 emulations.
+ */
+ if (type == HPDT_RM03 || type == HPDT_RM05) {
+ int hpsn = hpaddr->hpsn;
+
+ if ((hpsn & SIMB_LU) != mi->mi_drive)
+ return (type);
+ switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
+
+ case SI9775D:
+ printf("hp%d: 9775 (direct)\n", mi->mi_unit);
+ type = HPDT_9775;
+ break;
+
+ case SI9730D:
+ printf("hp%d: 9730 (direct)\n", mi->mi_unit);
+ type = HPDT_9730;
+ break;
+
+ /*
+ * Beware, since the only SI controller we
+ * have has a 9300 instead of a 9766, we map the
+ * drive type into the 9300. This means that
+ * on a 9766 you lose the last 8 cylinders (argh).
+ */
+ case SI9766:
+ printf("hp%d: 9300\n", mi->mi_unit);
+ type = HPDT_9300;
+ break;
+
+ case SI9762:
+ printf("hp%d: 9762\n", mi->mi_unit);
+ type = HPDT_RM03;
+ break;
+
+ case SICAPD:
+ printf("hp%d: capricorn\n", mi->mi_unit);
+ type = HPDT_CAPRICORN;
+ break;
+
+ case SI9751D:
+ printf("hp%d: eagle\n", mi->mi_unit);
+ type = HPDT_EAGLE;
+ break;
+ }
+ return (type);
+ }
+
+ /*
+ * EMULEX SC750 or SC780. Poke the holding register.
+ */
+ if (type == HPDT_RM02) {
+ int ntracks, nsectors;
+
+ hpaddr->hpof = HPOF_FMT22;
+ mbclrattn(mi);
+ hpaddr->hpcs1 = HP_NOP;
+ hpaddr->hphr = HPHR_MAXTRAK;
+ ntracks = MASKREG(hpaddr->hphr) + 1;
+ if (ntracks == 16) {
+ printf("hp%d: capricorn\n", mi->mi_unit);
+ type = HPDT_CAPRICORN;
+ goto done;
+ }
+ if (ntracks == 19) {
+ printf("hp%d: 9300\n", mi->mi_unit);
+ type = HPDT_9300;
+ goto done;
+ }
+ hpaddr->hpcs1 = HP_NOP;
+ hpaddr->hphr = HPHR_MAXSECT;
+ nsectors = MASKREG(hpaddr->hphr) + 1;
+ if (ntracks == 20 && nsectors == 48) {
+ type = HPDT_EAGLE;
+ printf("hp%d: eagle\n", mi->mi_unit);
+ goto done;
+ }
+ printf("hp%d: ntracks %d, nsectors %d: unknown device\n",
+ mi->mi_unit, ntracks, nsectors);
+done:
+ hpaddr->hpcs1 = HP_DCLR|HP_GO;
+ mbclrattn(mi); /* conservative */
+ return (type);
+ }
+
+ /*
+ * Map all ML11's to the same type. Also calculate
+ * transfer rates based on device characteristics.
+ */
+ if (type == HPDT_ML11A || type == HPDT_ML11B) {
+ register struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
+ register int trt;
+
+ sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
+ if ((hpaddr->hpmr & HPMR_ARRTYP) == 0)
+ sc->sc_mlsize >>= 2;
+ if (mi->mi_dk >= 0) {
+ trt = (hpaddr->hpmr & HPMR_TRT) >> 8;
+ dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt));
+ }
+ type = HPDT_ML11A;
+ }
+ return (type);
+}
+
+hpopen(dev)
+ dev_t dev;
+{
+ register int unit = hpunit(dev);
+ register struct mba_device *mi;
+
+ if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
+ return (ENXIO);
+ return (0);
+}
+