Exemple #1
0
static int
ahd_check_extport(struct ahd_softc *ahd)
{
	struct	vpd_config vpd;
	struct	seeprom_config *sc;
	u_int	adapter_control;
	int	have_seeprom;
	int	error;

	sc = ahd->seep_config;
	have_seeprom = ahd_acquire_seeprom(ahd);
	if (have_seeprom) {
		u_int start_addr;

		
		if (bootverbose) 
			printf("%s: Reading VPD from SEEPROM...",
			       ahd_name(ahd));

		
		start_addr = ((2 * sizeof(*sc))
			    + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;

		error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,
					 start_addr, sizeof(vpd)/2,
					 TRUE);
		if (error == 0)
			error = ahd_parse_vpddata(ahd, &vpd);
		if (bootverbose) 
			printf("%s: VPD parsing %s\n",
			       ahd_name(ahd),
			       error == 0 ? "successful" : "failed");

		if (bootverbose) 
			printf("%s: Reading SEEPROM...", ahd_name(ahd));

		
		start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');

		error = ahd_read_seeprom(ahd, (uint16_t *)sc,
					 start_addr, sizeof(*sc)/2,
					 FALSE);

		if (error != 0) {
			printf("Unable to read SEEPROM\n");
			have_seeprom = 0;
		} else {
			have_seeprom = ahd_verify_cksum(sc);

			if (bootverbose) {
				if (have_seeprom == 0)
					printf ("checksum error\n");
				else
					printf ("done.\n");
			}
		}
		ahd_release_seeprom(ahd);
	}

	if (!have_seeprom) {
		u_int	  nvram_scb;

		
		ahd_set_scbptr(ahd, 0xFF);
		nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
		if (nvram_scb != 0xFF
		 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
			uint16_t *sc_data;
			int	  i;

			ahd_set_scbptr(ahd, nvram_scb);
			sc_data = (uint16_t *)sc;
			for (i = 0; i < 64; i += 2)
				*sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
			have_seeprom = ahd_verify_cksum(sc);
			if (have_seeprom)
				ahd->flags |= AHD_SCB_CONFIG_USED;
		}
	}

#ifdef AHD_DEBUG
	if (have_seeprom != 0
	 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
		uint16_t *sc_data;
		int	  i;

		printf("%s: Seeprom Contents:", ahd_name(ahd));
		sc_data = (uint16_t *)sc;
		for (i = 0; i < (sizeof(*sc)); i += 2)
			printf("\n\t0x%.4x", sc_data[i]);
		printf("\n");
	}
#endif

	if (!have_seeprom) {
		if (bootverbose)
			printf("%s: No SEEPROM available.\n", ahd_name(ahd));
		ahd->flags |= AHD_USEDEFAULTS;
		error = ahd_default_config(ahd);
		adapter_control = CFAUTOTERM|CFSEAUTOTERM;
		free(ahd->seep_config, M_DEVBUF);
		ahd->seep_config = NULL;
	} else {
		error = ahd_parse_cfgdata(ahd, sc);
		adapter_control = sc->adapter_control;
	}
	if (error != 0)
		return (error);

	ahd_configure_termination(ahd, adapter_control);

	return (0);
}
Exemple #2
0
/*
 * Check the external port logic for a serial eeprom
 * and termination/cable detection contrls.
 */
static int
ahd_check_extport(struct ahd_softc *ahd)
{
	struct	vpd_config vpd;
	struct	seeprom_config *sc;
	u_int	adapter_control;
	int	have_seeprom;
	int	error;

	sc = ahd->seep_config;
	have_seeprom = ahd_acquire_seeprom(ahd);
	if (have_seeprom) {
		u_int start_addr;

		/*
		 * Fetch VPD for this function and parse it.
		 */
		if (bootverbose) 
			printf("%s: Reading VPD from SEEPROM...",
			       ahd_name(ahd));

		/* Address is always in units of 16bit words */
		start_addr = ((2 * sizeof(*sc))
			    + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;

		error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,
					 start_addr, sizeof(vpd)/2,
					 /*bytestream*/TRUE);
		if (error == 0)
			error = ahd_parse_vpddata(ahd, &vpd);
		if (bootverbose) 
			printf("%s: VPD parsing %s\n",
			       ahd_name(ahd),
			       error == 0 ? "successful" : "failed");

		if (bootverbose) 
			printf("%s: Reading SEEPROM...", ahd_name(ahd));

		/* Address is always in units of 16bit words */
		start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');

		error = ahd_read_seeprom(ahd, (uint16_t *)sc,
					 start_addr, sizeof(*sc)/2,
					 /*bytestream*/FALSE);

		if (error != 0) {
			printf("Unable to read SEEPROM\n");
			have_seeprom = 0;
		} else {
			have_seeprom = ahd_verify_cksum(sc);

			if (bootverbose) {
				if (have_seeprom == 0)
					printf ("checksum error\n");
				else
					printf ("done.\n");
			}
		}
		ahd_release_seeprom(ahd);
	}

	if (!have_seeprom) {
		u_int	  nvram_scb;

		/*
		 * Pull scratch ram settings and treat them as
		 * if they are the contents of an seeprom if
		 * the 'ADPT', 'BIOS', or 'ASPI' signature is found
		 * in SCB 0xFF.  We manually compose the data as 16bit
		 * values to avoid endian issues.
		 */
		ahd_set_scbptr(ahd, 0xFF);
		nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
		if (nvram_scb != 0xFF
		 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
			uint16_t *sc_data;
			int	  i;

			ahd_set_scbptr(ahd, nvram_scb);
			sc_data = (uint16_t *)sc;
			for (i = 0; i < 64; i += 2)
				*sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
			have_seeprom = ahd_verify_cksum(sc);
			if (have_seeprom)
				ahd->flags |= AHD_SCB_CONFIG_USED;
		}
	}

#ifdef AHD_DEBUG
	if (have_seeprom != 0
	 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
		uint16_t *sc_data;
		int	  i;

		printf("%s: Seeprom Contents:", ahd_name(ahd));
		sc_data = (uint16_t *)sc;
		for (i = 0; i < (sizeof(*sc)); i += 2)
			printf("\n\t0x%.4x", sc_data[i]);
		printf("\n");
	}
#endif

	if (!have_seeprom) {
		if (bootverbose)
			printf("%s: No SEEPROM available.\n", ahd_name(ahd));
		ahd->flags |= AHD_USEDEFAULTS;
		error = ahd_default_config(ahd);
		adapter_control = CFAUTOTERM|CFSEAUTOTERM;
		free(ahd->seep_config, M_DEVBUF);
		ahd->seep_config = NULL;
	} else {
		error = ahd_parse_cfgdata(ahd, sc);
		adapter_control = sc->adapter_control;
	}
	if (error != 0)
		return (error);

	ahd_configure_termination(ahd, adapter_control);

	return (0);
}
void
ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
{
    struct	scb *scb;
    struct	scsi_xfer *xs;
    struct	ahd_softc *ahd;
    struct	ahd_initiator_tinfo *tinfo;
    struct	ahd_tmode_tstate *tstate;
    u_int	mask;
    int	s;

    scb = (struct scb *)arg;
    xs = scb->xs;
    xs->error = CAM_REQ_INPROG;
    xs->status = 0;
    ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;

    if (nsegments != 0) {
        void *sg;
        int op;
        u_int i;

        ahd_setup_data_scb(ahd, scb);

        /* Copy the segments into our SG list */
        for (i = nsegments, sg = scb->sg_list; i > 0; i--) {

            sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
                              dm_segs->ds_len,
                              /*last*/i == 1);
            dm_segs++;
        }

        if ((xs->flags & SCSI_DATA_IN) != 0)
            op = BUS_DMASYNC_PREREAD;
        else
            op = BUS_DMASYNC_PREWRITE;

        bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
                        scb->dmamap->dm_mapsize, op);

    }

    ahd_lock(ahd, &s);

    /*
     * Last time we need to check if this SCB needs to
     * be aborted.
     */
    if (xs->flags & ITSDONE) {
        if (nsegments != 0)
            bus_dmamap_unload(ahd->parent_dmat,
                              scb->dmamap);
        ahd_free_scb(ahd, scb);
        ahd_unlock(ahd, &s);
        return;
    }

    tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
                                SCSIID_OUR_ID(scb->hscb->scsiid),
                                SCSIID_TARGET(ahd, scb->hscb->scsiid),
                                &tstate);

    mask = SCB_GET_TARGET_MASK(ahd, scb);

    if ((tstate->discenable & mask) != 0)
        scb->hscb->control |= DISCENB;

    if ((tstate->tagenable & mask) != 0)
        scb->hscb->control |= TAG_ENB;

    if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
        scb->flags |= SCB_PACKETIZED;
        if (scb->hscb->task_management != 0)
            scb->hscb->control &= ~MK_MESSAGE;
    }

    if ((tstate->auto_negotiate & mask) != 0) {
        scb->flags |= SCB_AUTO_NEGOTIATE;
        scb->hscb->control |= MK_MESSAGE;
    }

    /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */

    LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);

    if (!(xs->flags & SCSI_POLL))
        timeout_add_msec(&xs->stimeout, xs->timeout);

    scb->flags |= SCB_ACTIVE;

    if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
        /* Define a mapping from our tag to the SCB. */
        ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
        ahd_pause(ahd);
        ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
        ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
        ahd_unpause(ahd);
    } else {
        ahd_queue_scb(ahd, scb);
    }

    if (!(xs->flags & SCSI_POLL)) {
        int target = xs->sc_link->target;
        int lun = SCB_GET_LUN(scb);

        if (ahd->inited_target[target] == 0) {
            struct  ahd_devinfo devinfo;

            ahd_adapter_req_set_xfer_mode(ahd, scb);
            ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
                                'A', /*XXX milos*/ROLE_UNKNOWN);
            ahd_scb_devinfo(ahd, &devinfo, scb);
            ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
                                   AHD_NEG_IF_NON_ASYNC);
            ahd->inited_target[target] = 1;
        }

        ahd_unlock(ahd, &s);
        return;
    }

    /*
     * If we can't use interrupts, poll for completion
     */
    SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));

    do {
        if (ahd_poll(ahd, xs->timeout)) {
            if (!(xs->flags & SCSI_SILENT))
                printf("cmd fail\n");
            ahd_timeout(scb);
            break;
        }
    } while (!(xs->flags & ITSDONE));

    ahd_unlock(ahd, &s);
}