0001
0002
0003
0004
0005
0006
0007
0008 #include "saa7164.h"
0009
0010
0011
0012
0013 int saa7164_bus_setup(struct saa7164_dev *dev)
0014 {
0015 struct tmComResBusInfo *b = &dev->bus;
0016
0017 mutex_init(&b->lock);
0018
0019 b->Type = TYPE_BUS_PCIe;
0020 b->m_wMaxReqSize = SAA_DEVICE_MAXREQUESTSIZE;
0021
0022 b->m_pdwSetRing = (u8 __iomem *)(dev->bmmio +
0023 ((u32)dev->busdesc.CommandRing));
0024
0025 b->m_dwSizeSetRing = SAA_DEVICE_BUFFERBLOCKSIZE;
0026
0027 b->m_pdwGetRing = (u8 __iomem *)(dev->bmmio +
0028 ((u32)dev->busdesc.ResponseRing));
0029
0030 b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE;
0031
0032 b->m_dwSetWritePos = ((u32)dev->intfdesc.BARLocation) +
0033 (2 * sizeof(u64));
0034 b->m_dwSetReadPos = b->m_dwSetWritePos + (1 * sizeof(u32));
0035
0036 b->m_dwGetWritePos = b->m_dwSetWritePos + (2 * sizeof(u32));
0037 b->m_dwGetReadPos = b->m_dwSetWritePos + (3 * sizeof(u32));
0038
0039 return 0;
0040 }
0041
0042 void saa7164_bus_dump(struct saa7164_dev *dev)
0043 {
0044 struct tmComResBusInfo *b = &dev->bus;
0045
0046 dprintk(DBGLVL_BUS, "Dumping the bus structure:\n");
0047 dprintk(DBGLVL_BUS, " .type = %d\n", b->Type);
0048 dprintk(DBGLVL_BUS, " .dev->bmmio = 0x%p\n", dev->bmmio);
0049 dprintk(DBGLVL_BUS, " .m_wMaxReqSize = 0x%x\n", b->m_wMaxReqSize);
0050 dprintk(DBGLVL_BUS, " .m_pdwSetRing = 0x%p\n", b->m_pdwSetRing);
0051 dprintk(DBGLVL_BUS, " .m_dwSizeSetRing = 0x%x\n", b->m_dwSizeSetRing);
0052 dprintk(DBGLVL_BUS, " .m_pdwGetRing = 0x%p\n", b->m_pdwGetRing);
0053 dprintk(DBGLVL_BUS, " .m_dwSizeGetRing = 0x%x\n", b->m_dwSizeGetRing);
0054
0055 dprintk(DBGLVL_BUS, " .m_dwSetReadPos = 0x%x (0x%08x)\n",
0056 b->m_dwSetReadPos, saa7164_readl(b->m_dwSetReadPos));
0057
0058 dprintk(DBGLVL_BUS, " .m_dwSetWritePos = 0x%x (0x%08x)\n",
0059 b->m_dwSetWritePos, saa7164_readl(b->m_dwSetWritePos));
0060
0061 dprintk(DBGLVL_BUS, " .m_dwGetReadPos = 0x%x (0x%08x)\n",
0062 b->m_dwGetReadPos, saa7164_readl(b->m_dwGetReadPos));
0063
0064 dprintk(DBGLVL_BUS, " .m_dwGetWritePos = 0x%x (0x%08x)\n",
0065 b->m_dwGetWritePos, saa7164_readl(b->m_dwGetWritePos));
0066
0067 }
0068
0069
0070 static void saa7164_bus_verify(struct saa7164_dev *dev)
0071 {
0072 struct tmComResBusInfo *b = &dev->bus;
0073 int bug = 0;
0074
0075 if (saa7164_readl(b->m_dwSetReadPos) > b->m_dwSizeSetRing)
0076 bug++;
0077
0078 if (saa7164_readl(b->m_dwSetWritePos) > b->m_dwSizeSetRing)
0079 bug++;
0080
0081 if (saa7164_readl(b->m_dwGetReadPos) > b->m_dwSizeGetRing)
0082 bug++;
0083
0084 if (saa7164_readl(b->m_dwGetWritePos) > b->m_dwSizeGetRing)
0085 bug++;
0086
0087 if (bug) {
0088 saa_debug = 0xffff;
0089 saa7164_bus_dump(dev);
0090 saa_debug = 1024;
0091 BUG();
0092 }
0093 }
0094
0095 static void saa7164_bus_dumpmsg(struct saa7164_dev *dev, struct tmComResInfo *m,
0096 void *buf)
0097 {
0098 dprintk(DBGLVL_BUS, "Dumping msg structure:\n");
0099 dprintk(DBGLVL_BUS, " .id = %d\n", m->id);
0100 dprintk(DBGLVL_BUS, " .flags = 0x%x\n", m->flags);
0101 dprintk(DBGLVL_BUS, " .size = 0x%x\n", m->size);
0102 dprintk(DBGLVL_BUS, " .command = 0x%x\n", m->command);
0103 dprintk(DBGLVL_BUS, " .controlselector = 0x%x\n", m->controlselector);
0104 dprintk(DBGLVL_BUS, " .seqno = %d\n", m->seqno);
0105 if (buf)
0106 dprintk(DBGLVL_BUS, " .buffer (ignored)\n");
0107 }
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg,
0121 void *buf)
0122 {
0123 struct tmComResBusInfo *bus = &dev->bus;
0124 u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
0125 u32 new_swp, space_rem;
0126 int ret = SAA_ERR_BAD_PARAMETER;
0127 u16 size;
0128
0129 if (!msg) {
0130 printk(KERN_ERR "%s() !msg\n", __func__);
0131 return SAA_ERR_BAD_PARAMETER;
0132 }
0133
0134 dprintk(DBGLVL_BUS, "%s()\n", __func__);
0135
0136 saa7164_bus_verify(dev);
0137
0138 if (msg->size > dev->bus.m_wMaxReqSize) {
0139 printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
0140 __func__);
0141 return SAA_ERR_BAD_PARAMETER;
0142 }
0143
0144 if ((msg->size > 0) && (buf == NULL)) {
0145 printk(KERN_ERR "%s() Missing message buffer\n", __func__);
0146 return SAA_ERR_BAD_PARAMETER;
0147 }
0148
0149
0150 mutex_lock(&bus->lock);
0151
0152 bytes_to_write = sizeof(*msg) + msg->size;
0153 free_write_space = 0;
0154 timeout = SAA_BUS_TIMEOUT;
0155 curr_srp = saa7164_readl(bus->m_dwSetReadPos);
0156 curr_swp = saa7164_readl(bus->m_dwSetWritePos);
0157
0158
0159 if (curr_srp > curr_swp)
0160
0161 free_write_space = curr_srp - curr_swp;
0162 else
0163
0164 free_write_space = (curr_srp + bus->m_dwSizeSetRing) - curr_swp;
0165
0166 dprintk(DBGLVL_BUS, "%s() bytes_to_write = %d\n", __func__,
0167 bytes_to_write);
0168
0169 dprintk(DBGLVL_BUS, "%s() free_write_space = %d\n", __func__,
0170 free_write_space);
0171
0172 dprintk(DBGLVL_BUS, "%s() curr_srp = %x\n", __func__, curr_srp);
0173 dprintk(DBGLVL_BUS, "%s() curr_swp = %x\n", __func__, curr_swp);
0174
0175
0176 while (bytes_to_write >= free_write_space) {
0177
0178 if (timeout-- == 0) {
0179 printk(KERN_ERR "%s() bus timeout\n", __func__);
0180 ret = SAA_ERR_NO_RESOURCES;
0181 goto out;
0182 }
0183
0184
0185
0186 mdelay(1);
0187
0188
0189 curr_srp = saa7164_readl(bus->m_dwSetReadPos);
0190
0191
0192 if (curr_srp > curr_swp)
0193
0194 free_write_space = curr_srp - curr_swp;
0195 else
0196
0197 free_write_space = (curr_srp + bus->m_dwSizeSetRing) -
0198 curr_swp;
0199
0200 }
0201
0202
0203 new_swp = curr_swp + bytes_to_write;
0204
0205 dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
0206 dprintk(DBGLVL_BUS, "%s() bus->m_dwSizeSetRing = %x\n", __func__,
0207 bus->m_dwSizeSetRing);
0208
0209
0210
0211
0212
0213 size = msg->size;
0214
0215 msg->size = (__force u16)cpu_to_le16(msg->size);
0216 msg->command = (__force u32)cpu_to_le32(msg->command);
0217 msg->controlselector = (__force u16)cpu_to_le16(msg->controlselector);
0218
0219
0220
0221
0222 if (new_swp > bus->m_dwSizeSetRing) {
0223
0224
0225 new_swp -= bus->m_dwSizeSetRing;
0226
0227 space_rem = bus->m_dwSizeSetRing - curr_swp;
0228
0229 dprintk(DBGLVL_BUS, "%s() space_rem = %x\n", __func__,
0230 space_rem);
0231
0232 dprintk(DBGLVL_BUS, "%s() sizeof(*msg) = %d\n", __func__,
0233 (u32)sizeof(*msg));
0234
0235 if (space_rem < sizeof(*msg)) {
0236 dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
0237
0238
0239 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem);
0240 memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem,
0241 sizeof(*msg) - space_rem);
0242
0243 memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
0244 buf, size);
0245
0246 } else if (space_rem == sizeof(*msg)) {
0247 dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
0248
0249
0250 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
0251 memcpy_toio(bus->m_pdwSetRing, buf, size);
0252
0253 } else {
0254
0255 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
0256 if (size > 0) {
0257 memcpy_toio(bus->m_pdwSetRing + curr_swp +
0258 sizeof(*msg), buf, space_rem -
0259 sizeof(*msg));
0260 memcpy_toio(bus->m_pdwSetRing, (u8 *)buf +
0261 space_rem - sizeof(*msg),
0262 bytes_to_write - space_rem);
0263 }
0264
0265 }
0266
0267 }
0268 else {
0269 dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
0270
0271
0272 memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
0273 memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
0274 size);
0275 }
0276
0277 dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
0278
0279
0280 saa7164_writel(bus->m_dwSetWritePos, new_swp);
0281
0282
0283 msg->size = le16_to_cpu((__force __le16)msg->size);
0284 msg->command = le32_to_cpu((__force __le32)msg->command);
0285 msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector);
0286 ret = SAA_OK;
0287
0288 out:
0289 saa7164_bus_dump(dev);
0290 mutex_unlock(&bus->lock);
0291 saa7164_bus_verify(dev);
0292 return ret;
0293 }
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305 int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg,
0306 void *buf, int peekonly)
0307 {
0308 struct tmComResBusInfo *bus = &dev->bus;
0309 u32 bytes_to_read, write_distance, curr_grp, curr_gwp,
0310 new_grp, buf_size, space_rem;
0311 struct tmComResInfo msg_tmp;
0312 int ret = SAA_ERR_BAD_PARAMETER;
0313
0314 saa7164_bus_verify(dev);
0315
0316 if (msg == NULL)
0317 return ret;
0318
0319 if (msg->size > dev->bus.m_wMaxReqSize) {
0320 printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
0321 __func__);
0322 return ret;
0323 }
0324
0325 if ((peekonly == 0) && (msg->size > 0) && (buf == NULL)) {
0326 printk(KERN_ERR
0327 "%s() Missing msg buf, size should be %d bytes\n",
0328 __func__, msg->size);
0329 return ret;
0330 }
0331
0332 mutex_lock(&bus->lock);
0333
0334
0335
0336
0337 curr_gwp = saa7164_readl(bus->m_dwGetWritePos);
0338 curr_grp = saa7164_readl(bus->m_dwGetReadPos);
0339
0340 if (curr_gwp == curr_grp) {
0341 ret = SAA_ERR_EMPTY;
0342 goto out;
0343 }
0344
0345 bytes_to_read = sizeof(*msg);
0346
0347
0348 write_distance = 0;
0349 if (curr_gwp >= curr_grp)
0350
0351 write_distance = curr_gwp - curr_grp;
0352 else
0353
0354 write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
0355
0356 if (bytes_to_read > write_distance) {
0357 printk(KERN_ERR "%s() No message/response found\n", __func__);
0358 ret = SAA_ERR_INVALID_COMMAND;
0359 goto out;
0360 }
0361
0362
0363 new_grp = curr_grp + bytes_to_read;
0364 if (new_grp > bus->m_dwSizeGetRing) {
0365
0366
0367 new_grp -= bus->m_dwSizeGetRing;
0368 space_rem = bus->m_dwSizeGetRing - curr_grp;
0369
0370 memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
0371 memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
0372 bytes_to_read - space_rem);
0373
0374 } else {
0375
0376 memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
0377 }
0378
0379 msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size);
0380 msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command);
0381 msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector);
0382 memcpy(msg, &msg_tmp, sizeof(*msg));
0383
0384
0385
0386 if (peekonly) {
0387 goto peekout;
0388 }
0389
0390
0391 if ((msg_tmp.id != msg->id) || (msg_tmp.command != msg->command) ||
0392 (msg_tmp.controlselector != msg->controlselector) ||
0393 (msg_tmp.seqno != msg->seqno) || (msg_tmp.size != msg->size)) {
0394
0395 printk(KERN_ERR "%s() Unexpected msg miss-match\n", __func__);
0396 saa7164_bus_dumpmsg(dev, msg, buf);
0397 saa7164_bus_dumpmsg(dev, &msg_tmp, NULL);
0398 ret = SAA_ERR_INVALID_COMMAND;
0399 goto out;
0400 }
0401
0402
0403 buf_size = msg->size;
0404
0405 bytes_to_read = sizeof(*msg) + msg->size;
0406
0407 write_distance = 0;
0408 if (curr_gwp >= curr_grp)
0409
0410 write_distance = curr_gwp - curr_grp;
0411 else
0412
0413 write_distance = curr_gwp + bus->m_dwSizeGetRing - curr_grp;
0414
0415 if (bytes_to_read > write_distance) {
0416 printk(KERN_ERR "%s() Invalid bus state, missing msg or mangled ring, faulty H/W / bad code?\n",
0417 __func__);
0418 ret = SAA_ERR_INVALID_COMMAND;
0419 goto out;
0420 }
0421
0422
0423 new_grp = curr_grp + bytes_to_read;
0424 if (new_grp > bus->m_dwSizeGetRing) {
0425
0426
0427 new_grp -= bus->m_dwSizeGetRing;
0428 space_rem = bus->m_dwSizeGetRing - curr_grp;
0429
0430 if (space_rem < sizeof(*msg)) {
0431 if (buf)
0432 memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) -
0433 space_rem, buf_size);
0434
0435 } else if (space_rem == sizeof(*msg)) {
0436 if (buf)
0437 memcpy_fromio(buf, bus->m_pdwGetRing, buf_size);
0438 } else {
0439
0440 if (buf) {
0441 memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp +
0442 sizeof(*msg), space_rem - sizeof(*msg));
0443 memcpy_fromio(buf + space_rem - sizeof(*msg),
0444 bus->m_pdwGetRing, bytes_to_read -
0445 space_rem);
0446 }
0447
0448 }
0449
0450 } else {
0451
0452 if (buf)
0453 memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
0454 buf_size);
0455 }
0456
0457
0458 saa7164_writel(bus->m_dwGetReadPos, new_grp);
0459
0460 peekout:
0461 ret = SAA_OK;
0462 out:
0463 mutex_unlock(&bus->lock);
0464 saa7164_bus_verify(dev);
0465 return ret;
0466 }
0467