aha152x_stub.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*======================================================================
  2.     A driver for Adaptec AHA152X-compatible PCMCIA SCSI cards.
  3.     This driver supports the Adaptec AHA-1460, the New Media Bus
  4.     Toaster, and the New Media Toast & Jam.
  5.     
  6.     aha152x_cs.c 1.58 2001/10/13 00:08:51
  7.     The contents of this file are subject to the Mozilla Public
  8.     License Version 1.1 (the "License"); you may not use this file
  9.     except in compliance with the License. You may obtain a copy of
  10.     the License at http://www.mozilla.org/MPL/
  11.     Software distributed under the License is distributed on an "AS
  12.     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  13.     implied. See the License for the specific language governing
  14.     rights and limitations under the License.
  15.     The initial developer of the original code is David A. Hinds
  16.     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  17.     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  18.     Alternatively, the contents of this file may be used under the
  19.     terms of the GNU General Public License version 2 (the "GPL"), in
  20.     which case the provisions of the GPL are applicable instead of the
  21.     above.  If you wish to allow the use of your version of this file
  22.     only under the terms of the GPL and not to allow others to use
  23.     your version of this file under the MPL, indicate your decision
  24.     by deleting the provisions above and replace them with the notice
  25.     and other provisions required by the GPL.  If you do not delete
  26.     the provisions above, a recipient may use your version of this
  27.     file under either the MPL or the GPL.
  28.     
  29. ======================================================================*/
  30. #include <linux/module.h>
  31. #include <linux/init.h>
  32. #include <linux/kernel.h>
  33. #include <linux/sched.h>
  34. #include <linux/slab.h>
  35. #include <linux/string.h>
  36. #include <linux/timer.h>
  37. #include <linux/ioport.h>
  38. #include <scsi/scsi.h>
  39. #include <linux/major.h>
  40. #include <linux/blk.h>
  41. #include <../drivers/scsi/scsi.h>
  42. #include <../drivers/scsi/hosts.h>
  43. #include <scsi/scsi_ioctl.h>
  44. #include <../drivers/scsi/aha152x.h>
  45. #include <pcmcia/version.h>
  46. #include <pcmcia/cs_types.h>
  47. #include <pcmcia/cs.h>
  48. #include <pcmcia/cistpl.h>
  49. #include <pcmcia/ds.h>
  50. /*====================================================================*/
  51. /* Module parameters */
  52. MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  53. MODULE_DESCRIPTION("Adaptec AHA152x-compatible PCMCIA SCSI driver");
  54. MODULE_LICENSE("Dual MPL/GPL");
  55. static int irq_list[4] = { -1 };
  56. MODULE_PARM(irq_list, "1-4i");
  57. #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
  58. INT_MODULE_PARM(irq_mask, 0xdeb8);
  59. INT_MODULE_PARM(host_id, 7);
  60. INT_MODULE_PARM(reconnect, 1);
  61. INT_MODULE_PARM(parity, 1);
  62. INT_MODULE_PARM(synchronous, 0);
  63. INT_MODULE_PARM(reset_delay, 100);
  64. INT_MODULE_PARM(ext_trans, 0);
  65. #ifdef AHA152X_DEBUG
  66. INT_MODULE_PARM(debug, 0);
  67. #endif
  68. #ifdef PCMCIA_DEBUG
  69. INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
  70. #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
  71. static char *version =
  72. "aha152x_cs.c 1.58 2001/10/13 00:08:51 (David Hinds)";
  73. #else
  74. #define DEBUG(n, args...)
  75. #endif
  76. /*====================================================================*/
  77. typedef struct scsi_info_t {
  78.     dev_link_t link;
  79.     struct Scsi_Host *host;
  80.     int ndev;
  81.     dev_node_t node[8];
  82. } scsi_info_t;
  83. extern void aha152x_setup(char *str, int *ints);
  84. static void aha152x_release_cs(u_long arg);
  85. static int aha152x_event(event_t event, int priority,
  86.  event_callback_args_t *args);
  87. static dev_link_t *aha152x_attach(void);
  88. static void aha152x_detach(dev_link_t *);
  89. static Scsi_Host_Template driver_template = AHA152X;
  90. static dev_link_t *dev_list = NULL;
  91. static dev_info_t dev_info = "aha152x_cs";
  92. /*====================================================================*/
  93. static void cs_error(client_handle_t handle, int func, int ret)
  94. {
  95.     error_info_t err = { func, ret };
  96.     CardServices(ReportError, handle, &err);
  97. }
  98. /*====================================================================*/
  99. static dev_link_t *aha152x_attach(void)
  100. {
  101.     scsi_info_t *info;
  102.     client_reg_t client_reg;
  103.     dev_link_t *link;
  104.     int i, ret;
  105.     
  106.     DEBUG(0, "aha152x_attach()n");
  107.     /* Create new SCSI device */
  108.     info = kmalloc(sizeof(*info), GFP_KERNEL);
  109.     if (!info) return NULL;
  110.     memset(info, 0, sizeof(*info));
  111.     link = &info->link; link->priv = info;
  112.     link->release.function = &aha152x_release_cs;
  113.     link->release.data = (u_long)link;
  114.     link->io.NumPorts1 = 0x20;
  115.     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
  116.     link->io.IOAddrLines = 10;
  117.     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
  118.     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
  119.     if (irq_list[0] == -1)
  120. link->irq.IRQInfo2 = irq_mask;
  121.     else
  122. for (i = 0; i < 4; i++)
  123.     link->irq.IRQInfo2 |= 1 << irq_list[i];
  124.     link->conf.Attributes = CONF_ENABLE_IRQ;
  125.     link->conf.Vcc = 50;
  126.     link->conf.IntType = INT_MEMORY_AND_IO;
  127.     link->conf.Present = PRESENT_OPTION;
  128.     /* Register with Card Services */
  129.     link->next = dev_list;
  130.     dev_list = link;
  131.     client_reg.dev_info = &dev_info;
  132.     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
  133.     client_reg.event_handler = &aha152x_event;
  134.     client_reg.EventMask =
  135. CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
  136. CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
  137. CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
  138.     client_reg.Version = 0x0210;
  139.     client_reg.event_callback_args.client_data = link;
  140.     ret = CardServices(RegisterClient, &link->handle, &client_reg);
  141.     if (ret != 0) {
  142. cs_error(link->handle, RegisterClient, ret);
  143. aha152x_detach(link);
  144. return NULL;
  145.     }
  146.     
  147.     return link;
  148. } /* aha152x_attach */
  149. /*====================================================================*/
  150. static void aha152x_detach(dev_link_t *link)
  151. {
  152.     dev_link_t **linkp;
  153.     DEBUG(0, "aha152x_detach(0x%p)n", link);
  154.     
  155.     /* Locate device structure */
  156.     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
  157. if (*linkp == link) break;
  158.     if (*linkp == NULL)
  159. return;
  160.     del_timer(&link->release);
  161.     if (link->state & DEV_CONFIG) {
  162. aha152x_release_cs((u_long)link);
  163. if (link->state & DEV_STALE_CONFIG) {
  164.     link->state |= DEV_STALE_LINK;
  165.     return;
  166. }
  167.     }
  168.     if (link->handle)
  169. CardServices(DeregisterClient, link->handle);
  170.     
  171.     /* Unlink device structure, free bits */
  172.     *linkp = link->next;
  173.     kfree(link->priv);
  174.     
  175. } /* aha152x_detach */
  176. /*====================================================================*/
  177. #define CS_CHECK(fn, args...) 
  178. while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
  179. #define CFG_CHECK(fn, args...) 
  180. if (CardServices(fn, args) != 0) goto next_entry
  181. static void aha152x_config_cs(dev_link_t *link)
  182. {
  183.     client_handle_t handle = link->handle;
  184.     scsi_info_t *info = link->priv;
  185.     tuple_t tuple;
  186.     cisparse_t parse;
  187.     int i, last_ret, last_fn, ints[8];
  188.     u_char tuple_data[64];
  189.     Scsi_Device *dev;
  190.     dev_node_t *node, **tail;
  191.     struct Scsi_Host *host;
  192.     
  193.     DEBUG(0, "aha152x_config(0x%p)n", link);
  194.     tuple.DesiredTuple = CISTPL_CONFIG;
  195.     tuple.TupleData = tuple_data;
  196.     tuple.TupleDataMax = 64;
  197.     tuple.TupleOffset = 0;
  198.     CS_CHECK(GetFirstTuple, handle, &tuple);
  199.     CS_CHECK(GetTupleData, handle, &tuple);
  200.     CS_CHECK(ParseTuple, handle, &tuple, &parse);
  201.     link->conf.ConfigBase = parse.config.base;
  202.     /* Configure card */
  203.     driver_template.module = &__this_module;
  204.     link->state |= DEV_CONFIG;
  205.     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
  206.     CS_CHECK(GetFirstTuple, handle, &tuple);
  207.     while (1) {
  208. CFG_CHECK(GetTupleData, handle, &tuple);
  209. CFG_CHECK(ParseTuple, handle, &tuple, &parse);
  210. /* For New Media T&J, look for a SCSI window */
  211. if (parse.cftable_entry.io.win[0].len >= 0x20)
  212.     link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
  213. else if ((parse.cftable_entry.io.nwin > 1) &&
  214.  (parse.cftable_entry.io.win[1].len >= 0x20))
  215.     link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
  216. if ((parse.cftable_entry.io.nwin > 0) &&
  217.     (link->io.BasePort1 < 0xffff)) {
  218.     link->conf.ConfigIndex = parse.cftable_entry.index;
  219.     i = CardServices(RequestIO, handle, &link->io);
  220.     if (i == CS_SUCCESS) break;
  221. }
  222.     next_entry:
  223. CS_CHECK(GetNextTuple, handle, &tuple);
  224.     }
  225.     
  226.     CS_CHECK(RequestIRQ, handle, &link->irq);
  227.     CS_CHECK(RequestConfiguration, handle, &link->conf);
  228.     
  229.     /* A bad hack... */
  230.     release_region(link->io.BasePort1, link->io.NumPorts1);
  231.     
  232.     /* Set configuration options for the aha152x driver */
  233.     ints[1] = link->io.BasePort1;
  234.     ints[2] = link->irq.AssignedIRQ;
  235.     ints[3] = host_id;
  236.     ints[4] = reconnect;
  237.     ints[5] = parity;
  238.     ints[6] = synchronous;
  239.     ints[7] = reset_delay;
  240.     ints[8] = ext_trans;
  241. #ifdef AHA152X_DEBUG
  242.     ints[9] = debug;
  243.     ints[0] = 9;
  244. #else
  245.     ints[0] = 8;
  246. #endif
  247.     aha152x_setup("PCMCIA setup", ints);
  248.     
  249.     scsi_register_module(MODULE_SCSI_HA, &driver_template);
  250.     tail = &link->dev;
  251.     info->ndev = 0;
  252.     for (host = scsi_hostlist; host; host = host->next)
  253. if (host->hostt == &driver_template)
  254.     for (dev = host->host_queue; dev; dev = dev->next) {
  255.     u_long arg[2], id;
  256.     kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);
  257.     id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +
  258. ((arg[0]>>8)&0xf00) + ((arg[0]>>12)&0xf000);
  259.     node = &info->node[info->ndev];
  260.     node->minor = 0;
  261.     switch (dev->type) {
  262.     case TYPE_TAPE:
  263. node->major = SCSI_TAPE_MAJOR;
  264. sprintf(node->dev_name, "st#%04lx", id);
  265. break;
  266.     case TYPE_DISK:
  267.     case TYPE_MOD:
  268. node->major = SCSI_DISK0_MAJOR;
  269. sprintf(node->dev_name, "sd#%04lx", id);
  270. break;
  271.     case TYPE_ROM:
  272.     case TYPE_WORM:
  273. node->major = SCSI_CDROM_MAJOR;
  274. sprintf(node->dev_name, "sr#%04lx", id);
  275. break;
  276.     default:
  277. node->major = SCSI_GENERIC_MAJOR;
  278. sprintf(node->dev_name, "sg#%04lx", id);
  279. break;
  280.     }
  281.     *tail = node; tail = &node->next;
  282.     info->ndev++;
  283.     info->host = dev->host;
  284. }
  285.     *tail = NULL;
  286.     if (info->ndev == 0)
  287. printk(KERN_INFO "aha152x_cs: no SCSI devices foundn");
  288.     
  289.     link->state &= ~DEV_CONFIG_PENDING;
  290.     return;
  291.     
  292. cs_failed:
  293.     cs_error(link->handle, last_fn, last_ret);
  294.     aha152x_release_cs((u_long)link);
  295.     return;
  296.     
  297. } /* aha152x_config_cs */
  298. /*====================================================================*/
  299. static void aha152x_release_cs(u_long arg)
  300. {
  301.     dev_link_t *link = (dev_link_t *)arg;
  302.     DEBUG(0, "aha152x_release_cs(0x%p)n", link);
  303.     if (GET_USE_COUNT(driver_template.module) != 0) {
  304. DEBUG(1, "aha152x_cs: release postponed, "
  305.       "device still openn");
  306. link->state |= DEV_STALE_CONFIG;
  307. return;
  308.     }
  309.     scsi_unregister_module(MODULE_SCSI_HA, &driver_template);
  310.     link->dev = NULL;
  311.     
  312.     CardServices(ReleaseConfiguration, link->handle);
  313.     CardServices(ReleaseIO, link->handle, &link->io);
  314.     CardServices(ReleaseIRQ, link->handle, &link->irq);
  315.     
  316.     link->state &= ~DEV_CONFIG;
  317.     if (link->state & DEV_STALE_LINK)
  318. aha152x_detach(link);
  319.     
  320. } /* aha152x_release_cs */
  321. /*====================================================================*/
  322. static int aha152x_event(event_t event, int priority,
  323.  event_callback_args_t *args)
  324. {
  325.     dev_link_t *link = args->client_data;
  326.     scsi_info_t *info = link->priv;
  327.     
  328.     DEBUG(0, "aha152x_event(0x%06x)n", event);
  329.     
  330.     switch (event) {
  331.     case CS_EVENT_CARD_REMOVAL:
  332. link->state &= ~DEV_PRESENT;
  333. if (link->state & DEV_CONFIG)
  334.     mod_timer(&link->release, jiffies + HZ/20);
  335. break;
  336.     case CS_EVENT_CARD_INSERTION:
  337. link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
  338. aha152x_config_cs(link);
  339. break;
  340.     case CS_EVENT_PM_SUSPEND:
  341. link->state |= DEV_SUSPEND;
  342. /* Fall through... */
  343.     case CS_EVENT_RESET_PHYSICAL:
  344. if (link->state & DEV_CONFIG)
  345.     CardServices(ReleaseConfiguration, link->handle);
  346. break;
  347.     case CS_EVENT_PM_RESUME:
  348. link->state &= ~DEV_SUSPEND;
  349. /* Fall through... */
  350.     case CS_EVENT_CARD_RESET:
  351. if (link->state & DEV_CONFIG) {
  352.     Scsi_Cmnd tmp;
  353.     CardServices(RequestConfiguration, link->handle, &link->conf);
  354.     tmp.host = info->host;
  355.     aha152x_host_reset(&tmp);
  356. }
  357. break;
  358.     }
  359.     return 0;
  360. } /* aha152x_event */
  361. /*====================================================================*/
  362. static int __init init_aha152x_cs(void) {
  363.     servinfo_t serv;
  364.     DEBUG(0, "%sn", version);
  365.     CardServices(GetCardServicesInfo, &serv);
  366.     if (serv.Revision != CS_RELEASE_CODE) {
  367. printk(KERN_NOTICE "aha152x_cs: Card Services release "
  368.        "does not match!n");
  369. return -1;
  370.     }
  371.     register_pccard_driver(&dev_info, &aha152x_attach, &aha152x_detach);
  372.     return 0;
  373. }
  374. static void __exit exit_aha152x_cs(void) {
  375.     DEBUG(0, "aha152x_cs: unloadingn");
  376.     unregister_pccard_driver(&dev_info);
  377.     while (dev_list != NULL)
  378. aha152x_detach(dev_list);
  379. }
  380. module_init(init_aha152x_cs);
  381. module_exit(exit_aha152x_cs);
  382.