/* * Implementation of Utility functions for all SCSI device types. * * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. * Copyright (c) 1997, 1998 Kenneth D. Merry. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.38 2002/09/23 04:56:35 mjacob Exp $ * $Id$ */ #include "aiclib.h" /* * Table of syncrates that don't follow the "divisible by 4" * rule. This table will be expanded in future SCSI specs. */ static struct { u_int period_factor; u_int period; /* in 100ths of ns */ } scsi_syncrates[] = { { 0x08, 625 }, /* FAST-160 */ { 0x09, 1250 }, /* FAST-80 */ { 0x0a, 2500 }, /* FAST-40 40MHz */ { 0x0b, 3030 }, /* FAST-40 33MHz */ { 0x0c, 5000 } /* FAST-20 */ }; /* * Return the frequency in kHz corresponding to the given * sync period factor. */ u_int aic_calc_syncsrate(u_int period_factor) { int i; int num_syncrates; num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); /* See if the period is in the "exception" table */ for (i = 0; i < num_syncrates; i++) { if (period_factor == scsi_syncrates[i].period_factor) { /* Period in kHz */ return (100000000 / scsi_syncrates[i].period); } } /* * Wasn't in the table, so use the standard * 4 times conversion. */ return (10000000 / (period_factor * 4 * 10)); } char * aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, aic_option_callback_t *callback, u_long callback_arg) { char *tok_end; char *tok_end2; int i; int instance; int targ; int done; char tok_list[] = {'.', ',', '{', '}', '\0'}; /* All options use a ':' name/arg separator */ if (*opt_arg != ':') return (opt_arg); opt_arg++; instance = -1; targ = -1; done = FALSE; /* * Restore separator that may be in * the middle of our option argument. */ tok_end = strchr(opt_arg, '\0'); if (tok_end < end) *tok_end = ','; while (!done) { switch (*opt_arg) { case '{': if (instance == -1) { instance = 0; } else { if (depth > 1) { if (targ == -1) targ = 0; } else { printf("Malformed Option %s\n", opt_name); done = TRUE; } } opt_arg++; break; case '}': if (targ != -1) targ = -1; else if (instance != -1) instance = -1; opt_arg++; break; case ',': case '.': if (instance == -1) done = TRUE; else if (targ >= 0) targ++; else if (instance >= 0) instance++; opt_arg++; break; case '\0': done = TRUE; break; default: tok_end = end; for (i = 0; tok_list[i]; i++) { tok_end2 = strchr(opt_arg, tok_list[i]); if ((tok_end2) && (tok_end2 < tok_end)) tok_end = tok_end2; } callback(callback_arg, instance, targ, simple_strtol(opt_arg, NULL, 0)); opt_arg = tok_end; break; } } return (opt_arg); }