Esempio n. 1
0
static void
subseg_set_rest (segT seg, subsegT subseg)
{
  frchainS *frcP;		/* crawl frchain chain */
  frchainS **lastPP;		/* address of last pointer */
  frchainS *newP;		/* address of new frchain */
  segment_info_type *seginfo;

  mri_common_symbol = NULL;

  if (frag_now && frchain_now)
    frchain_now->frch_frag_now = frag_now;

  gas_assert (frchain_now == 0
	  || frchain_now->frch_last == frag_now);

  subseg_change (seg, (int) subseg);

  seginfo = seg_info (seg);

  /* Attempt to find or make a frchain for that subsection.
     We keep the list sorted by subsection number.  */
  for (frcP = *(lastPP = &seginfo->frchainP);
       frcP != NULL;
       frcP = *(lastPP = &frcP->frch_next))
    if (frcP->frch_subseg >= subseg)
      break;

  if (frcP == NULL || frcP->frch_subseg != subseg)
    {
      /* This should be the only code that creates a frchainS.  */

      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
      newP->frch_subseg = subseg;
      newP->fix_root = NULL;
      newP->fix_tail = NULL;
      obstack_begin (&newP->frch_obstack, chunksize);
#if __GNUC__ >= 2
      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
#endif
      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
      newP->frch_frag_now->fr_type = rs_fill;
      newP->frch_cfi_data = NULL;

      newP->frch_root = newP->frch_last = newP->frch_frag_now;

      *lastPP = newP;
      newP->frch_next = frcP;
      frcP = newP;
    }

  frchain_now = frcP;
  frag_now = frcP->frch_frag_now;

  gas_assert (frchain_now->frch_last == frag_now);
}
Esempio n. 2
0
void
frag_new (int old_frags_var_max_size
	  /* Number of chars (already allocated on obstack frags) in
	     variable_length part of frag.  */)
{
  fragS *former_last_fragP;
  frchainS *frchP;

  assert (frchain_now->frch_last == frag_now);

  /* Fix up old frag's fr_fix.  */
  frag_now->fr_fix = frag_now_fix_octets () - old_frags_var_max_size;
  /* Make sure its type is valid.  */
  assert (frag_now->fr_type != 0);

  /* This will align the obstack so the next struct we allocate on it
     will begin at a correct boundary.  */
  obstack_finish (&frchain_now->frch_obstack);
  frchP = frchain_now;
  know (frchP);
  former_last_fragP = frchP->frch_last;
  assert (former_last_fragP != 0);
  assert (former_last_fragP == frag_now);
  frag_now = frag_alloc (&frchP->frch_obstack);

  as_where (&frag_now->fr_file, &frag_now->fr_line);

  /* Generally, frag_now->points to an address rounded up to next
     alignment.  However, characters will add to obstack frags
     IMMEDIATELY after the struct frag, even if they are not starting
     at an alignment address.  */
  former_last_fragP->fr_next = frag_now;
  frchP->frch_last = frag_now;

#ifndef NO_LISTING
  {
    extern struct list_info_struct *listing_tail;
    frag_now->line = listing_tail;
  }
#endif

  assert (frchain_now->frch_last == frag_now);

  frag_now->fr_next = NULL;
}
Esempio n. 3
0
static void
wds_scsi_io(struct cam_sim * sim, struct ccb_scsiio * csio)
{
	int	 unit = cam_sim_unit(sim);
	struct	 wds *wp;
	struct	 ccb_hdr *ccb_h;
	struct	 wds_req *r;
	int	 base;
	u_int8_t c;
	int	 error;
	int	 n;

	wp = (struct wds *)cam_sim_softc(sim);
	ccb_h = &csio->ccb_h;

	DBG(DBX "wds%d: cmd TARG=%d LUN=%d\n", unit, ccb_h->target_id,
	    ccb_h->target_lun);

	if (ccb_h->target_id > 7 || ccb_h->target_id == WDS_HBA_ID) {
		ccb_h->status = CAM_TID_INVALID;
		xpt_done((union ccb *) csio);
		return;
	}
	if (ccb_h->target_lun > 7) {
		ccb_h->status = CAM_LUN_INVALID;
		xpt_done((union ccb *) csio);
		return;
	}
	if (csio->dxfer_len > BUFSIZ) {
		ccb_h->status = CAM_REQ_TOO_BIG;
		xpt_done((union ccb *) csio);
		return;
	}
	if ((ccb_h->flags & CAM_DATA_MASK) != CAM_DATA_VADDR) {
		/* don't support these */
		ccb_h->status = CAM_REQ_INVALID;
		xpt_done((union ccb *) csio);
		return;
	}
	base = wp->addr;

	/*
	 * this check is mostly for debugging purposes,
	 * "can't happen" normally.
	 */
	if(wp->want_wdsr) {
		DBG(DBX "wds%d: someone already waits for buffer\n", unit);
		smallog('b');
		n = xpt_freeze_simq(sim, /* count */ 1);
		smallog('0'+n);
		ccb_h->status = CAM_REQUEUE_REQ;
		xpt_done((union ccb *) csio);
		return;
	}

	r = wdsr_alloc(wp);
	if (r == NULL) {
		device_printf(wp->dev, "no request slot available!\n");
		wp->want_wdsr = 1;
		n = xpt_freeze_simq(sim, /* count */ 1);
		smallog2('f', '0'+n);
		ccb_h->status = CAM_REQUEUE_REQ;
		xpt_done((union ccb *) csio);
		return;
	}

	ccb_h->ccb_wdsr = (void *) r;
	r->ccb = (union ccb *) csio;

	switch (error = frag_alloc(wp, csio->dxfer_len, &r->buf, &r->mask)) {
	case CAM_REQ_CMP:
		break;
	case CAM_REQUEUE_REQ:
		DBG(DBX "wds%d: no data buffer available\n", unit);
		wp->want_wdsr = 1;
		n = xpt_freeze_simq(sim, /* count */ 1);
		smallog2('f', '0'+n);
		wdsr_ccb_done(wp, r, r->ccb, CAM_REQUEUE_REQ);
		return;
	default:
		DBG(DBX "wds%d: request is too big\n", unit);
		wdsr_ccb_done(wp, r, r->ccb, error);
		break;
	}

	ccb_h->status |= CAM_SIM_QUEUED;
	r->flags &= ~WR_DONE;

	scsi_ulto3b(WDSTOPHYS(wp, &r->cmd), wp->dx->ombs[r->ombn].addr);

	bzero(&r->cmd, sizeof r->cmd);
	r->cmd.cmd = WDSX_SCSICMD;
	r->cmd.targ = (ccb_h->target_id << 5) | ccb_h->target_lun;

	if (ccb_h->flags & CAM_CDB_POINTER)
		bcopy(csio->cdb_io.cdb_ptr, &r->cmd.scb,
		      csio->cdb_len < 12 ? csio->cdb_len : 12);
	else
		bcopy(csio->cdb_io.cdb_bytes, &r->cmd.scb,
		      csio->cdb_len < 12 ? csio->cdb_len : 12);

	scsi_ulto3b(csio->dxfer_len, r->cmd.len);

	if (csio->dxfer_len > 0
	 && (ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
		/* we already rejected physical or scattered addresses */
		bcopy(csio->data_ptr, r->buf, csio->dxfer_len);
	}
	scsi_ulto3b(csio->dxfer_len ? WDSTOPHYS(wp, r->buf) : 0, r->cmd.data);

	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN)
		r->cmd.write = 0x80;
	else
		r->cmd.write = 0x00;

	scsi_ulto3b(0, r->cmd.next);

	outb(base + WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);

	c = WDSC_MSTART(r->ombn);

	if (wds_cmd(base, &c, sizeof c) != 0) {
		device_printf(wp->dev, "unable to start outgoing mbox\n");
		wp->dx->ombs[r->ombn].stat = 0;
		wdsr_ccb_done(wp, r, r->ccb, CAM_RESRC_UNAVAIL);
		return;
	}
	DBG(DBX "wds%d: enqueued cmd 0x%x, r=%p\n", unit,
	    r->cmd.scb[0] & 0xFF, r);

	smallog3('+', ccb_h->target_id + '0', ccb_h->target_lun + '0');
}