Exemplo n.º 1
0
/*
 *  Scan through a PCI expansion ROM, and create subregions for each
 *  ROM image. This function assumes that the ROM is mapped at
 *  (tag,handle), and that the expansion ROM address decoder is
 *  enabled. The PCI specification requires that no other BAR should
 *  be accessed while the ROM is enabled, so interrupts should be
 *  disabled.
 *
 * XXX This routine is way too pessimistic and returns as soon as it encounters
 * a problem, although not being able to malloc or read a particular image
 * may not prevent further images from being read successfully.
 */
int
cardbus_read_exrom(bus_space_tag_t romt, bus_space_handle_t romh,
    struct cardbus_rom_image_head *head)
{
	size_t addr = 0; /* offset of current rom image */
	size_t dataptr;
	unsigned int rom_image = 0;
	size_t image_size;
	struct cardbus_rom_image *image;
	u_int16_t val;

	SIMPLEQ_INIT(head);
	do {
		val = READ_INT16(romt, romh, addr + CARDBUS_EXROM_SIGNATURE);
		if (val != 0xaa55) {
			DPRINTF(("%s: bad header signature in ROM image "
			    "%u: 0x%04x\n", __func__, rom_image, val));
			return (1);
		}
		dataptr = addr + READ_INT16(romt, romh,
		    addr + CARDBUS_EXROM_DATA_PTR);

		/* get the ROM image size, in blocks */
		image_size = READ_INT16(romt, romh,
		    dataptr + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
		/* XXX
		 * Some ROMs seem to have this as zero, can we assume
		 * this means 1 block?
		 */
		if (image_size == 0)
			image_size = 1;
		image_size <<= 9;

		image = malloc(sizeof(*image), M_DEVBUF, M_NOWAIT);
		if (image == NULL) {
			DPRINTF(("%s: out of memory\n", __func__));
			return (1);
		}
		image->rom_image = rom_image;
		image->image_size = image_size;
		image->romt = romt;
		if (bus_space_subregion(romt, romh, addr,
		    image_size, &image->romh)) {
			DPRINTF(("%s: bus_space_subregion failed", __func__));
			free(image, M_DEVBUF, sizeof(*image));
			return (1);
		}
		SIMPLEQ_INSERT_TAIL(head, image, next);
		addr += image_size;
		rom_image++;
	} while ((bus_space_read_1(romt, romh,
	    dataptr + CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0);

	return (0);
}
Exemplo n.º 2
0
void
spc_tag_get_info (guchar * data, guint length, spc_tag_info * info)
{
  spc_tag_clear (info);

  if (spc_tag_is_present (data, length)) {
    gboolean text_format = spc_tag_is_text_format (data, length);

    info->title = g_new0 (gchar, 0x21);
    info->game = g_new0 (gchar, 0x21);
    info->artist = g_new0 (gchar, 0x21);
    info->dumper = g_new0 (gchar, 0x10);
    info->comment = g_new0 (gchar, 0x32);

    strncpy (info->title, (gchar *) & data[0x2E], 32);
    strncpy (info->artist, (gchar *) & data[(text_format ? 0xB1 : 0xB0)], 32);
    strncpy (info->game, (gchar *) & data[0x4E], 32);
    strncpy (info->dumper, (gchar *) & data[0x6E], 16);
    strncpy (info->comment, (gchar *) & data[0x7E], 32);

    if (text_format) {
      gchar time[4];
      gchar fade[6];
      guint dump_year, dump_month, dump_day;

      strncpy (time, (gchar *) data + 0xA9, 3);
      strncpy (fade, (gchar *) data + 0xAC, 5);

      time[3] = fade[5] = 0;

      info->time_seconds = atoi (time);
      info->time_fade_milliseconds = atoi (fade);

      dump_year = (guint) atoi ((gchar *) data + 0x9E);
      dump_month = (guint) atoi ((gchar *) data + 0x9E + 3);
      dump_day = (guint) atoi ((gchar *) data + 0x9E + 3 + 3);

      if (dump_month == 0)
        dump_month = 1;
      if (dump_day == 0)
        dump_day = 1;
      if (dump_year != 0)
        info->dump_date = g_date_new_dmy (dump_day, dump_month, dump_year);

      info->muted = READ_INT8 (data, 0xD1);
      info->emulator = READ_INT8 (data, 0xD2);
    } else {
      info->time_seconds = READ_INT24 (data, 0xA9);
      info->time_fade_milliseconds = READ_INT32 (data, 0xAC);
      info->dump_date = spc_tag_unpack_date (READ_INT32 (data, 0x9E));
      info->muted = READ_INT8 (data, 0xD0);
      info->emulator = READ_INT8 (data, 0xD1);
    }
  }

  if (spc_tag_is_extended (data, length)) {
    guchar *chunk = data + EXTENDED_OFFSET + 8;
    guint32 chunk_size = *((guint32 *) (data + EXTENDED_OFFSET + 4));

    guchar *subchunk, *subchunk_next;

    for (subchunk = chunk; subchunk < chunk + chunk_size;
        subchunk = subchunk_next) {
      guint8 tag = READ_INT8 (subchunk, 0);
      guint8 type = READ_INT8 (subchunk, 1);
      guint16 length = READ_INT16 (subchunk, 2);
      guchar *value = subchunk + 4;

      switch (type) {
        case TYPE_LENGTH:
        {
          switch (tag) {
            case TAG_TRACK:
              info->track = READ_INT8 (subchunk, 2 + 1);
              break;
            case TAG_YEAR:
              info->year = READ_INT16 (subchunk, 2);
              break;
            case TAG_COUNT:
              info->loop_count = READ_INT8 (subchunk, 2);
              break;
            case TAG_EMULATOR:
              info->emulator = READ_INT8 (subchunk, 2);
              break;
            case TAG_DISC:
              info->disc = READ_INT8 (subchunk, 2);
              break;
            case TAG_MUTED:
              info->muted = READ_INT8 (subchunk, 2);
              break;
            default:
              break;
          }

          subchunk_next = subchunk + 4;
          break;
        }
        case TYPE_STRING:
        {
          gchar *dest;

          if (length <= 1)
            dest = NULL;
          else
            switch (tag) {
              case TAG_TITLE:
                dest = info->title = g_renew (gchar, info->title, length);
                break;
              case TAG_GAME:
                dest = info->game = g_renew (gchar, info->game, length);
                break;
              case TAG_ARTIST:
                dest = info->artist = g_renew (gchar, info->artist, length);
                break;
              case TAG_ALBUM:
                dest = info->album = g_renew (gchar, info->album, length);
                break;
              case TAG_DUMPER:
                dest = info->dumper = g_renew (gchar, info->dumper, length);
                break;
              case TAG_COMMENT:
                dest = info->comment = g_renew (gchar, info->comment, length);
                break;
              case TAG_PUBLISHER:
                dest = info->publisher =
                    g_renew (gchar, info->publisher, length);
                break;
              default:
                dest = NULL;
                break;
            }

          if (dest)
            strncpy (dest, (gchar *) value, length);

          subchunk_next = value + length;
          break;
        }
        case TYPE_INTEGER:
        {
          switch (tag) {
            case TAG_INTRO:
              info->time_intro = READ_INT32 (value, 0);
              break;
            case TAG_END:
              info->time_end = READ_INT32 (value, 0);
              break;
            case TAG_FADE:
              info->time_fade = READ_INT32 (value, 0);
              break;
            case TAG_LOOP:
              info->time_loop = READ_INT32 (value, 0);
              break;
            case TAG_DUMP_DATE:
              info->dump_date = spc_tag_unpack_date (READ_INT32 (value, 0));
              break;
            case TAG_AMP:
              info->amplification = READ_INT32 (value, 0);
              break;
            default:
              break;
          }
          subchunk_next = value + length;
          break;
        }
        default:
          subchunk_next = value + length;
          break;
      }
    }
  }

  if (info->title && !*info->title) {
    g_free (info->title);
    info->title = NULL;
  }
  if (info->game && !*info->game) {
    g_free (info->game);
    info->game = NULL;
  }
  if (info->artist && !*info->artist) {
    g_free (info->artist);
    info->artist = NULL;
  }
  if (info->album && !*info->album) {
    g_free (info->album);
    info->album = NULL;
  }
  if (info->publisher && !*info->publisher) {
    g_free (info->publisher);
    info->publisher = NULL;
  }
  if (info->comment && !*info->comment) {
    g_free (info->comment);
    info->comment = NULL;
  }
  if (info->dumper && !*info->dumper) {
    g_free (info->dumper);
    info->dumper = NULL;
  }
}