1 /* 2 Mantis PCI bridge driver 3 4 Copyright (C) Manu Abraham (abraham.manu@gmail.com) 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20 21 #include <linux/signal.h> 22 #include <linux/slab.h> 23 #include <linux/sched.h> 24 #include <linux/interrupt.h> 25 #include <asm/io.h> 26 27 #include <media/dmxdev.h> 28 #include <media/dvbdev.h> 29 #include <media/dvb_demux.h> 30 #include <media/dvb_frontend.h> 31 #include <media/dvb_net.h> 32 33 #include "mantis_common.h" 34 #include "mantis_link.h" 35 #include "mantis_hif.h" 36 #include "mantis_reg.h" 37 38 #include "mantis_ca.h" 39 40 static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr) 41 { 42 struct mantis_ca *ca = en50221->data; 43 struct mantis_pci *mantis = ca->ca_priv; 44 45 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot); 46 47 if (slot != 0) 48 return -EINVAL; 49 50 return mantis_hif_read_mem(ca, addr); 51 } 52 53 static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data) 54 { 55 struct mantis_ca *ca = en50221->data; 56 struct mantis_pci *mantis = ca->ca_priv; 57 58 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot); 59 60 if (slot != 0) 61 return -EINVAL; 62 63 return mantis_hif_write_mem(ca, addr, data); 64 } 65 66 static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr) 67 { 68 struct mantis_ca *ca = en50221->data; 69 struct mantis_pci *mantis = ca->ca_priv; 70 71 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot); 72 73 if (slot != 0) 74 return -EINVAL; 75 76 return mantis_hif_read_iom(ca, addr); 77 } 78 79 static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data) 80 { 81 struct mantis_ca *ca = en50221->data; 82 struct mantis_pci *mantis = ca->ca_priv; 83 84 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot); 85 86 if (slot != 0) 87 return -EINVAL; 88 89 return mantis_hif_write_iom(ca, addr, data); 90 } 91 92 static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot) 93 { 94 struct mantis_ca *ca = en50221->data; 95 struct mantis_pci *mantis = ca->ca_priv; 96 97 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot); 98 udelay(500); /* Wait.. */ 99 mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */ 100 udelay(500); 101 mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */ 102 msleep(1000); 103 dvb_ca_en50221_camready_irq(&ca->en50221, 0); 104 105 return 0; 106 } 107 108 static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot) 109 { 110 struct mantis_ca *ca = en50221->data; 111 struct mantis_pci *mantis = ca->ca_priv; 112 113 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot); 114 115 return 0; 116 } 117 118 static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot) 119 { 120 struct mantis_ca *ca = en50221->data; 121 struct mantis_pci *mantis = ca->ca_priv; 122 123 dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot); 124 /* mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */ 125 126 return 0; 127 } 128 129 static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open) 130 { 131 struct mantis_ca *ca = en50221->data; 132 struct mantis_pci *mantis = ca->ca_priv; 133 134 dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot); 135 136 if (ca->slot_state == MODULE_INSERTED) { 137 dprintk(MANTIS_DEBUG, 1, "CA Module present and ready"); 138 return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; 139 } else { 140 dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready"); 141 } 142 143 return 0; 144 } 145 146 int mantis_ca_init(struct mantis_pci *mantis) 147 { 148 struct dvb_adapter *dvb_adapter = &mantis->dvb_adapter; 149 struct mantis_ca *ca; 150 int ca_flags = 0, result; 151 152 dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA"); 153 ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL); 154 if (!ca) { 155 dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting .."); 156 result = -ENOMEM; 157 goto err; 158 } 159 160 ca->ca_priv = mantis; 161 mantis->mantis_ca = ca; 162 ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE; 163 /* register CA interface */ 164 ca->en50221.owner = THIS_MODULE; 165 ca->en50221.read_attribute_mem = mantis_ca_read_attr_mem; 166 ca->en50221.write_attribute_mem = mantis_ca_write_attr_mem; 167 ca->en50221.read_cam_control = mantis_ca_read_cam_ctl; 168 ca->en50221.write_cam_control = mantis_ca_write_cam_ctl; 169 ca->en50221.slot_reset = mantis_ca_slot_reset; 170 ca->en50221.slot_shutdown = mantis_ca_slot_shutdown; 171 ca->en50221.slot_ts_enable = mantis_ts_control; 172 ca->en50221.poll_slot_status = mantis_slot_status; 173 ca->en50221.data = ca; 174 175 mutex_init(&ca->ca_lock); 176 177 init_waitqueue_head(&ca->hif_data_wq); 178 init_waitqueue_head(&ca->hif_opdone_wq); 179 init_waitqueue_head(&ca->hif_write_wq); 180 181 dprintk(MANTIS_ERROR, 1, "Registering EN50221 device"); 182 result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1); 183 if (result != 0) { 184 dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result); 185 goto err; 186 } 187 dprintk(MANTIS_ERROR, 1, "Registered EN50221 device"); 188 mantis_evmgr_init(ca); 189 return 0; 190 err: 191 kfree(ca); 192 return result; 193 } 194 EXPORT_SYMBOL_GPL(mantis_ca_init); 195 196 void mantis_ca_exit(struct mantis_pci *mantis) 197 { 198 struct mantis_ca *ca = mantis->mantis_ca; 199 200 dprintk(MANTIS_DEBUG, 1, "Mantis CA exit"); 201 if (!ca) 202 return; 203 204 mantis_evmgr_exit(ca); 205 dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device"); 206 dvb_ca_en50221_release(&ca->en50221); 207 208 kfree(ca); 209 } 210 EXPORT_SYMBOL_GPL(mantis_ca_exit); 211