static int
ahd_pci_intr(struct ahd_softc *ahd)
{
	uint8_t			pci_status[8];
	ahd_mode_state		saved_modes;
	u_int			pci_status1;
	u_int			intstat;
	u_int			i;
	u_int			reg;
	struct ahd_pci_busdata 	*bd = ahd->bus_data;

	intstat = ahd_inb(ahd, INTSTAT);

	if ((intstat & SPLTINT) != 0)
		ahd_pci_split_intr(ahd, intstat);

	if ((intstat & PCIINT) == 0)
		return 0;

	printf("%s: PCI error Interrupt\n", ahd_name(ahd));
	saved_modes = ahd_save_modes(ahd);
	ahd_dump_card_state(ahd);
	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
	for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {

		if (i == 5)
			continue;
		pci_status[i] = ahd_inb(ahd, reg);
		/* Clear latched errors.  So our interrupt deasserts. */
		ahd_outb(ahd, reg, pci_status[i]);
	}

	for (i = 0; i < 8; i++) {
		u_int bit;

		if (i == 5)
			continue;

		for (bit = 0; bit < 8; bit++) {

			if ((pci_status[i] & (0x1 << bit)) != 0) {
				static const char *s;

				s = pci_status_strings[bit];
				if (i == 7/*TARG*/ && bit == 3)
					s = "%s: Signaled Target Abort\n";
				printf(s, ahd_name(ahd), pci_status_source[i]);
			}
		}
	}
	pci_status1 = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG);
	pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG , pci_status1);

	ahd_restore_modes(ahd, saved_modes);
	ahd_outb(ahd, CLRINT, CLRPCIINT);
	ahd_unpause(ahd);

	return 1;
}
Example #2
0
static void
ahd_pci_intr(struct ahd_softc *ahd)
{
	uint8_t		pci_status[8];
	ahd_mode_state	saved_modes;
	u_int		pci_status1;
	u_int		intstat;
	u_int		i;
	u_int		reg;
	
	intstat = ahd_inb(ahd, INTSTAT);

	if ((intstat & SPLTINT) != 0)
		ahd_pci_split_intr(ahd, intstat);

	if ((intstat & PCIINT) == 0)
		return;

	printf("%s: PCI error Interrupt\n", ahd_name(ahd));
	saved_modes = ahd_save_modes(ahd);
	ahd_dump_card_state(ahd);
	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
	for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {

		if (i == 5)
			continue;
		pci_status[i] = ahd_inb(ahd, reg);
		
		ahd_outb(ahd, reg, pci_status[i]);
	}

	for (i = 0; i < 8; i++) {
		u_int bit;
	
		if (i == 5)
			continue;

		for (bit = 0; bit < 8; bit++) {

			if ((pci_status[i] & (0x1 << bit)) != 0) {
				static const char *s;

				s = pci_status_strings[bit];
				if (i == 7 && bit == 3)
					s = "%s: Signaled Target Abort\n";
				printf(s, ahd_name(ahd), pci_status_source[i]);
			}
		}	
	}
	pci_status1 = ahd_pci_read_config(ahd->dev_softc,
					  PCIR_STATUS + 1, 1);
	ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
			     pci_status1, 1);
	ahd_restore_modes(ahd, saved_modes);
	ahd_outb(ahd, CLRINT, CLRPCIINT);
	ahd_unpause(ahd);
}
Example #3
0
static int
ahd_proc_write_seeprom(struct ahd_softc *ahd, char *buffer, int length)
{
	ahd_mode_state saved_modes;
	int have_seeprom;
	u_long s;
	int paused;
	int written;

	/* Default to failure. */
	written = -EINVAL;
	ahd_lock(ahd, &s);
	paused = ahd_is_paused(ahd);
	if (!paused)
		ahd_pause(ahd);

	saved_modes = ahd_save_modes(ahd);
	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
	if (length != sizeof(struct seeprom_config)) {
		printf("ahd_proc_write_seeprom: incorrect buffer size\n");
		goto done;
	}

	have_seeprom = ahd_verify_cksum((struct seeprom_config*)buffer);
	if (have_seeprom == 0) {
		printf("ahd_proc_write_seeprom: cksum verification failed\n");
		goto done;
	}

	have_seeprom = ahd_acquire_seeprom(ahd);
	if (!have_seeprom) {
		printf("ahd_proc_write_seeprom: No Serial EEPROM\n");
		goto done;
	} else {
		u_int start_addr;

		if (ahd->seep_config == NULL) {
			ahd->seep_config = malloc(sizeof(*ahd->seep_config),
						  M_DEVBUF, M_NOWAIT);
			if (ahd->seep_config == NULL) {
				printf("aic79xx: Unable to allocate serial "
				       "eeprom buffer.  Write failing\n");
				goto done;
			}
		}
		printf("aic79xx: Writing Serial EEPROM\n");
		start_addr = 32 * (ahd->channel - 'A');
		ahd_write_seeprom(ahd, (u_int16_t *)buffer, start_addr,
				  sizeof(struct seeprom_config)/2);
		ahd_read_seeprom(ahd, (uint16_t *)ahd->seep_config,
				 start_addr, sizeof(struct seeprom_config)/2,
				 /*ByteStream*/FALSE);
		ahd_release_seeprom(ahd);
		written = length;
	}

done:
	ahd_restore_modes(ahd, saved_modes);
	if (!paused)
		ahd_unpause(ahd);
	ahd_unlock(ahd, &s);
	return (written);
}
Example #4
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);
}