1 /*======================================================================
3 A utility to convert a plain text description of a Card
4 Information Structure into its packed binary representation.
6 pack_cis.c 1.20 2002/10/16 16:38:18
8 The contents of this file are subject to the Mozilla Public
9 License Version 2.0 (the "License"); you may not use this file
10 except in compliance with the License. You may obtain a copy of
11 the License at http://www.mozilla.org/MPL/
13 Software distributed under the License is distributed on an "AS
14 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 rights and limitations under the License.
18 The initial developer of the original code is David A. Hinds
19 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
20 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
22 Alternatively, the contents of this file may be used under the
23 terms of the GNU General Public License version 2 (the "GPL"), in
24 which case the provisions of the GPL are applicable instead of the
25 above. If you wish to allow the use of your version of this file
26 only under the terms of the GPL and not to allow others to use
27 your version of this file under the MPL, indicate your decision
28 by deleting the provisions above and replace them with the notice
29 and other provisions required by the GPL. If you do not delete
30 the provisions above, a recipient may use your version of this
31 file under either the MPL or the GPL.
35 pack_cis [-o outfile] [infile]
37 [infile] defaults to stdin, and [outfile] defaults to stdout.
39 ======================================================================*/
41 #include <sys/types.h>
48 #include <pcmcia/cs_types.h>
49 #include <pcmcia/cs.h>
50 #include <pcmcia/cistpl.h>
54 tuple_info_t *cis_root = NULL, *mfc[8] = { NULL };
57 /*======================================================================
59 Support routines for packing parts of configuration table entries
61 ======================================================================*/
63 static u_int mantissa[] = {
64 10, 12, 13, 15, 20, 25, 30, 35,
65 40, 45, 50, 55, 60, 70, 80, 90
67 static int pack_power(cistpl_power_t *pwr, u_char *b)
70 u_char m, e, x, *c = b;
71 *c = pwr->present; c++;
72 for (i = 0; i < 7; i++) {
73 if (!(pwr->present & (1<<i)))
76 for (e = 1; ((tmp % 10) == 0) || (tmp > 999); e++)
80 if (tmp < 10) { tmp *= 10; e--; }
81 for (m = 0; m < 16; m++)
82 if (mantissa[m] == tmp) break;
83 if (m == 16) { tmp *= 10; e--; }
87 x = (tmp/10) - ((tmp/10) % 10);
88 for (m = 0; m < 16; m++)
89 if (mantissa[m] == x) break;
90 x = (u_char)(tmp - 10*(u_int)x);
92 *c = (m<<3) | e | (x ? 0x80 : 0); c++;
93 if (x) { *c = x; c++; }
98 static int pack_io(cistpl_io_t *p, u_char *b)
102 *c = p->flags & (CISTPL_IO_8BIT|CISTPL_IO_16BIT);
103 if ((p->nwin == 1) && (p->win[0].base == 0)) {
104 for (i = 1, j = 0; i < p->win[0].len; i *= 2, j++) ;
107 for (i = ma = ml = 0; i < p->nwin; i++) {
108 ma |= p->win[i].base;
109 ml |= p->win[i].len-1;
111 ma = (ma > 0xffff) ? 3 : ((ma > 0xff) ? 2 : 1);
112 ml = (ml > 0xffff) ? 3 : ((ml > 0xff) ? 2 : 1);
113 *c |= 0x80 | (p->flags & CISTPL_IO_LINES_MASK); c++;
114 *c = (p->nwin-1) | (ma<<4) | (ml<<6); c++;
115 if (ma == 3) ma++; if (ml == 3) ml++;
116 for (i = 0; i < p->nwin; i++) {
117 for (j = 0; j < ma; j++) {
118 *c = (p->win[i].base >> (8*j)) & 0xff; c++;
120 for (j = 0; j < ml; j++) {
121 *c = ((p->win[i].len-1) >> (8*j)) & 0xff; c++;
128 static int pack_mem(cistpl_mem_t *p, u_char *b)
131 u_int i, j, ml, ma, ha;
132 for (i = ma = ml = ha = 0; i < p->nwin; i++) {
133 ma |= p->win[i].card_addr;
135 ha |= p->win[i].host_addr;
137 ma = (ma|ha) >> 8; ml >>= 8;
138 ma = (ma > 0xffff) ? 3 : ((ma > 0xff) ? 2 : 1);
139 ml = (ml > 0xffff) ? 3 : ((ml > 0xff) ? 2 : 1);
140 *c = (p->nwin-1) | (ma<<5) | (ml<<3) | (ha ? 0x80 : 0); c++;
141 for (i = 0; i < p->nwin; i++) {
142 for (j = 1; j <= ml; j++) {
143 *c = (p->win[i].len >> (8*j)) & 0xff; c++;
145 for (j = 1; j <= ma; j++) {
146 *c = (p->win[i].card_addr >> (8*j)) & 0xff; c++;
149 for (j = 1; j <= ma; j++) {
150 *c = (p->win[i].host_addr >> (8*j)) & 0xff; c++;
156 static int pack_irq(cistpl_irq_t *p, u_char *b)
159 if (p->IRQInfo1 & IRQ_INFO2_VALID) {
160 b[1] = p->IRQInfo2 & 0xff;
161 b[2] = (p->IRQInfo2 >> 8) & 0xff;
167 static void pack_cftable(cistpl_cftable_entry_t *p, u_char *b)
170 b[2] = p->index | 0x80;
171 if (p->flags & CISTPL_CFTABLE_DEFAULT)
174 b[3] |= (p->flags & CISTPL_CFTABLE_BVDS) ? 0x10 : 0;
175 b[3] |= (p->flags & CISTPL_CFTABLE_WP) ? 0x20 : 0;
176 b[3] |= (p->flags & CISTPL_CFTABLE_RDYBSY) ? 0x40 : 0;
177 b[3] |= (p->flags & CISTPL_CFTABLE_MWAIT) ? 0x80 : 0;
180 if (p->vcc.present) {
181 b[4]++; c += pack_power(&p->vcc, c);
182 if (p->vpp1.present) {
183 b[4]++; c += pack_power(&p->vpp1, c);
184 if (p->vpp2.present) {
185 b[4]++; c += pack_power(&p->vpp2, c);
189 if (p->io.nwin > 0) {
191 c += pack_io(&p->io, c);
193 if (p->irq.IRQInfo1 > 0) {
195 c += pack_irq(&p->irq, c);
197 if (p->mem.nwin > 0) {
199 c += pack_mem(&p->mem, c);
203 *c++ = p->flags >> 8;
208 /*======================================================================
210 Routines for packing device info tuples
212 ======================================================================*/
214 static int pack_speed(u_int speed, u_char *b)
218 case 0: *c |= 0; c++; break;
219 case 250: *c |= 1; c++; break;
220 case 200: *c |= 2; c++; break;
221 case 150: *c |= 3; c++; break;
222 case 100: *c |= 4; c++; break;
225 for (e = 1; speed > 80; e++)
227 for (m = 0; m < 15; m++)
228 if (mantissa[m] >= speed) break;
229 *c = ((m+1)<<3) | e; c++;
234 static void pack_device(cistpl_device_t *d, u_char *b)
238 for (i = 0; i < d->ndev; i++) {
239 *c = (d->dev[i].type<<4);
240 c += pack_speed(d->dev[i].speed, c);
241 sz = d->dev[i].size/512;
242 for (e = 0; sz > 32; e++)
244 *c = (e & 7) | ((sz-1) << 3); c++;
250 /*======================================================================
252 For now, I only implement a subset of tuples types, intended to be
253 enough to handle most IO-oriented cards.
255 ======================================================================*/
257 static int pack_tuple(tuple_info_t *t, u_char *b)
259 cisparse_t *p = t->parse;
266 case CISTPL_DEVICE_A:
268 pack_device(&p->device, b);
270 /* Fake null device tuple */
271 b[1] = 3; b[2] = 0; b[3] = 0; b[4] = 0xff;
276 b[2] = p->manfid.manf & 0xff;
277 b[3] = p->manfid.manf >> 8;
278 b[4] = p->manfid.card & 0xff;
279 b[5] = p->manfid.card >> 8;
283 b[2] = p->funcid.func;
284 b[3] = p->funcid.sysinit;
288 b[1] = 2*p->jedec.nid;
289 for (i = 0; i < p->jedec.nid; i++) {
290 b[2*i+1] = p->jedec.id[i].mfr;
291 b[2*i+2] = p->jedec.id[i].info;
295 b[3] = p->config.last_idx;
297 for (c = b+4, m = 0; (i > 0) || !m; i >>= 8, m++) {
301 i = p->config.rmask[0];
302 for (c = c+m, m = 0; (i > 0) || !m; i >>= 8, m++) {
305 b[2] |= ((m-1) << 2);
309 b[2] = p->version_1.major;
310 b[3] = p->version_1.minor;
312 for (i = 0; i < p->version_1.ns; i++) {
313 strcpy((char *)c, p->version_1.str+p->version_1.ofs[i]);
314 c += strlen((char *)c) + 1;
316 for (; i < 4; i++) { *c = 0; c++; }
320 case CISTPL_CFTABLE_ENTRY:
321 pack_cftable(&p->cftable_entry, b);
323 case CISTPL_LINKTARGET:
324 b[1] = 3; b[2] = 'C'; b[3] = 'I'; b[4] = 'S';
334 /*======================================================================
336 The following routines handle parsing of aggregates of tuples.
337 pack_chain() is the simplest: just return a string of tuples and
338 terminate with an END tuple. pack_mfc() is used to tie the
339 function-specific tuple chains for a multifunction card together
340 using a LONGLINK_MFC tuple. And pack_cis() handles a complete
341 CIS, whether it is multifunction or not.
343 ======================================================================*/
345 static int pack_chain(tuple_info_t *t, u_char *b)
348 tuple_info_t end = { CISTPL_END, NULL, NULL };
350 n += pack_tuple(t, b+n);
353 n += pack_tuple(&end, b+n);
357 static int pack_mfc(u_int ofs, u_char *b)
360 tuple_info_t target = { CISTPL_LINKTARGET, NULL, NULL };
362 b[0] = CISTPL_LONGLINK_MFC;
365 b[5*nf+3] = CISTPL_END;
367 /* Leave space for this tuple and the CISTPL_END tuple */
369 for (i = 0; i < nf; i++) {
371 for (j = 0; j < 4; j++)
372 b[4+i*5+j] = ((ofs+pos) >> (8*j)) & 0xff;
373 pos += pack_tuple(&target, b+pos);
374 pos += pack_chain(mfc[i], b+pos);
379 static int pack_cis(tuple_info_t *t, u_char *b)
382 tuple_info_t device = { CISTPL_DEVICE, NULL, NULL };
383 tuple_info_t nolink = { CISTPL_NO_LINK, NULL, NULL };
384 tuple_info_t end = { CISTPL_END, NULL, NULL };
385 if (t->type != CISTPL_DEVICE)
386 n = pack_tuple(&device, b);
388 n += pack_tuple(t, b+n);
392 n = pack_mfc(n, b+n);
394 n += pack_tuple(&nolink, b+n);
395 n += pack_tuple(&end, b+n);
400 /*====================================================================*/
402 int main(int argc, char *argv[])
404 int optch, errflg = 0;
410 while ((optch = getopt(argc, argv, "o:")) != -1) {
413 out = strdup(optarg); break;
418 if (errflg || (optind < argc-1)) {
419 fprintf(stderr, "usage: %s [-o outfile] [infile]\n",
424 f = fopen(argv[optind], "r");
426 fprintf(stderr, "could not open '%s': %s\n", argv[optind],
434 n = pack_cis(cis_root, buf);
438 fprintf(stderr, "could not open '%s': %s\n", out,
443 fwrite(buf, n, 1, f);