static int powernow_decode_bios()

in powernow-k7.c [447:522]


static int powernow_decode_bios(int maxfid, int startvid)
{
	struct psb_s *psb;
	struct pst_s *pst;
	unsigned int i, j;
	unsigned char *p;
	unsigned int etuple;
	unsigned int ret;

	etuple = cpuid_eax(0x80000001);

	for (i = 0xC0000; i < 0xffff0 ; i += 16) {

		p = phys_to_virt(i);

		if (memcmp(p, "AMDK7PNOW!",  10) == 0) {
			pr_debug("Found PSB header at %p\n", p);
			psb = (struct psb_s *) p;
			pr_debug("Table version: 0x%x\n", psb->tableversion);
			if (psb->tableversion != 0x12) {
				pr_info("Sorry, only v1.2 tables supported right now\n");
				return -ENODEV;
			}

			pr_debug("Flags: 0x%x\n", psb->flags);
			if ((psb->flags & 1) == 0)
				pr_debug("Mobile voltage regulator\n");
			else
				pr_debug("Desktop voltage regulator\n");

			latency = psb->settlingtime;
			if (latency < 100) {
				pr_info("BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n",
					latency);
				latency = 100;
			}
			pr_debug("Settling Time: %d microseconds.\n",
					psb->settlingtime);
			pr_debug("Has %d PST tables. (Only dumping ones "
					"relevant to this CPU).\n",
					psb->numpst);

			p += sizeof(*psb);

			pst = (struct pst_s *) p;

			for (j = 0; j < psb->numpst; j++) {
				pst = (struct pst_s *) p;
				number_scales = pst->numpstates;

				if ((etuple == pst->cpuid) &&
				    check_fsb(pst->fsbspeed) &&
				    (maxfid == pst->maxfid) &&
				    (startvid == pst->startvid)) {
					print_pst_entry(pst, j);
					p = (char *)pst + sizeof(*pst);
					ret = get_ranges(p);
					return ret;
				} else {
					unsigned int k;
					p = (char *)pst + sizeof(*pst);
					for (k = 0; k < number_scales; k++)
						p += 2;
				}
			}
			pr_info("No PST tables match this cpuid (0x%x)\n",
				etuple);
			pr_info("This is indicative of a broken BIOS\n");

			return -EINVAL;
		}
		p++;
	}

	return -ENODEV;
}