// SPDX-License-Identifier: (GPL-2.0 OR MPL-1.1) /*======================================================================
A driver for PCMCIA serial devices
serial_cs.c 1.134 2002/05/04 05:48:53
The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License.
The initial developer of the original code is David A. Hinds <dahinds@users.sourceforge.net>. Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the terms of the GNU General Public License version 2 (the "GPL"), in which case the provisions of the GPL are applicable instead of the above. If you wish to allow the use of your version of this file only under the terms of the GPL and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL.
struct serial_info { struct pcmcia_device *p_dev; int ndev; int multi; int slave; int manfid; int prodid; int c950ctrl; int line[4]; conststruct serial_quirk *quirk;
};
/* * vers_1 5.0, "Brain Boxes", "2-Port RS232 card", "r6" * manfid 0x0160, 0x0104 * This card appears to have a 14.7456MHz clock.
*/ /* Generic Modem: MD55x (GPRS/EDGE) have * Elan VPU16551 UART with 14.7456MHz oscillator * manfid 0x015D, 0x4C45
*/ staticvoid quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_8250_port *uart)
{
uart->port.uartclk = 14745600;
}
staticint quirk_post_ibm(struct pcmcia_device *link)
{
u8 val; int ret;
ret = pcmcia_read_config_byte(link, 0x800, &val); if (ret) goto failed;
ret = pcmcia_write_config_byte(link, 0x800, val | 1); if (ret) goto failed; return 0;
failed: return -ENODEV;
}
/* * Nokia cards are not really multiport cards. Shouldn't this * be handled by setting the quirk entry .multi = 0 | 1 ?
*/ staticvoid quirk_config_nokia(struct pcmcia_device *link)
{ struct serial_info *info = link->priv;
if (info->c950ctrl)
outb(12, info->c950ctrl + 1);
}
/* request_region? oxsemi branch does no request_region too... */ /* * This sequence is needed to properly initialize MC45 attached to OXCF950. * I tried decreasing these msleep()s, but it worked properly (survived * 1000 stop/start operations) with these timeouts (or bigger).
*/ staticvoid quirk_wakeup_possio_gcc(struct pcmcia_device *link)
{ struct serial_info *info = link->priv; unsignedint ctrl = info->c950ctrl;
/* * First pass: look for a config entry that looks normal. * Two tries: without IO aliases, then with aliases.
*/
link->config_flags |= CONF_AUTO_SET_VPP; for (try = 0; try < 4; try++) if (!pcmcia_loop_config(link, simple_config_check, &try)) goto found_port;
/* * Second pass: try to find an entry that isn't picky about * its base address, then try to grab any standard serial port * address, and finally try to get any free port.
*/
ret = pcmcia_loop_config(link, simple_config_check_notpicky, NULL); if (ret) {
dev_warn(&link->dev, "no usable port range found, giving up\n"); return ret;
}
found_port: if (info->multi && (info->manfid == MANFID_3COM))
link->config_index &= ~(0x08);
/* * Apply any configuration quirks.
*/ if (info->quirk && info->quirk->config)
info->quirk->config(link);
ret = pcmcia_enable_device(link); if (ret != 0) return ret; return setup_serial(link, info, link->resource[0]->start, link->irq);
}
/* * The quad port cards have bad CIS's, so just look for a * window larger than 8 ports and assume it will be right.
*/ if (p_dev->resource[0]->end <= 8) return -EINVAL;
staticint multi_config(struct pcmcia_device *link)
{ struct serial_info *info = link->priv; int i, base2 = 0;
/* First, look for a generic full-sized window */ if (!pcmcia_loop_config(link, multi_config_check, &info->multi))
base2 = link->resource[0]->start + 8; else { /* If that didn't work, look for two windows */
info->multi = 2; if (pcmcia_loop_config(link, multi_config_check_notpicky,
&base2)) {
dev_warn(&link->dev, "no usable port range found, giving up\n"); return -ENODEV;
}
}
if (!link->irq)
dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
/* * Apply any configuration quirks.
*/ if (info->quirk && info->quirk->config)
info->quirk->config(link);
i = pcmcia_enable_device(link); if (i != 0) return -ENODEV;
/* The Oxford Semiconductor OXCF950 cards are in fact single-port: * 8 registers are for the UART, the others are extra registers. * Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
*/ if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
info->prodid == PRODID_POSSIO_GCC)) { if (link->config_index == 1 ||
link->config_index == 3) {
setup_serial(link, info, base2, link->irq);
base2 = link->resource[0]->start;
} else {
setup_serial(link, info, link->resource[0]->start,
link->irq);
}
info->c950ctrl = base2;
/* * FIXME: We really should wake up the port prior to * handing it over to the serial layer.
*/ if (info->quirk && info->quirk->wakeup)
info->quirk->wakeup(link);
return 0;
}
setup_serial(link, info, link->resource[0]->start, link->irq); for (i = 0; i < info->multi - 1; i++)
setup_serial(link, info, base2 + (8 * i),
link->irq); return 0;
}
/* Is this a compliant multifunction card? */
info->multi = (link->socket->functions > 1);
/* Is this a multiport card? */
info->manfid = link->manf_id;
info->prodid = link->card_id;
for (i = 0; i < ARRAY_SIZE(quirks); i++) if ((quirks[i].manfid == ~0 ||
quirks[i].manfid == info->manfid) &&
(quirks[i].prodid == ~0 ||
quirks[i].prodid == info->prodid)) {
info->quirk = &quirks[i]; break;
}
/* * Another check for dual-serial cards: look for either serial or * multifunction cards that ask for appropriate IO port ranges.
*/ if ((info->multi == 0) &&
(link->has_func_id) &&
(link->socket->pcmcia_pfc == 0) &&
((link->func_id == CISTPL_FUNCID_MULTI) ||
(link->func_id == CISTPL_FUNCID_SERIAL))) { if (pcmcia_loop_config(link, serial_check_for_multi, info)) goto failed;
}
/* * Apply any multi-port quirk.
*/ if (info->quirk && info->quirk->multi != -1)
info->multi = info->quirk->multi;
dev_info(&link->dev, "trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
link->manf_id, link->card_id,
link->socket->pcmcia_pfc, info->multi, info->quirk); if (link->socket->pcmcia_pfc)
i = pfc_config(link); elseif (info->multi > 1)
i = multi_config(link); else
i = simple_config(link);
if (i || info->ndev == 0) goto failed;
/* * Apply any post-init quirk. FIXME: This should really happen * before we register the port, since it might already be in use.
*/ if (info->quirk && info->quirk->post) if (info->quirk->post(link)) goto failed;
return 0;
failed:
dev_warn(&link->dev, "failed to initialize\n");
serial_remove(link); return -ENODEV;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.